@oneuptime/common 8.0.5312 → 8.0.5329

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 (124) hide show
  1. package/Models/DatabaseModels/GlobalConfig.ts +90 -0
  2. package/Models/DatabaseModels/Index.ts +4 -0
  3. package/Models/DatabaseModels/Project.ts +27 -0
  4. package/Models/DatabaseModels/UserNotificationRule.ts +48 -0
  5. package/Models/DatabaseModels/UserNotificationSetting.ts +16 -0
  6. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +48 -0
  7. package/Models/DatabaseModels/UserWhatsApp.ts +288 -0
  8. package/Models/DatabaseModels/WhatsAppLog.ts +884 -0
  9. package/Server/API/NotificationAPI.ts +4 -4
  10. package/Server/API/ProjectSSO.ts +41 -33
  11. package/Server/API/ShortLinkAPI.ts +33 -25
  12. package/Server/API/UserCallAPI.ts +82 -73
  13. package/Server/API/UserEmailAPI.ts +82 -73
  14. package/Server/API/UserOnCallLogTimelineAPI.ts +227 -214
  15. package/Server/API/UserPushAPI.ts +177 -169
  16. package/Server/API/UserSmsAPI.ts +82 -73
  17. package/Server/API/UserWhatsAppAPI.ts +136 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1759838763506-MigrationName.ts +103 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1759839342566-MigrationName.ts +71 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  21. package/Server/Services/Index.ts +4 -0
  22. package/Server/Services/MonitorService.ts +32 -4
  23. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +36 -4
  24. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +34 -4
  25. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +34 -4
  26. package/Server/Services/OnCallDutyPolicyScheduleService.ts +47 -6
  27. package/Server/Services/ProbeService.ts +17 -2
  28. package/Server/Services/UserNotificationRuleService.ts +258 -7
  29. package/Server/Services/UserNotificationSettingService.ts +60 -0
  30. package/Server/Services/UserWhatsAppService.ts +203 -0
  31. package/Server/Services/WhatsAppLogService.ts +15 -0
  32. package/Server/Services/WhatsAppService.ts +141 -0
  33. package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +17 -5
  34. package/Server/Types/Workflow/Components/Webhook.ts +2 -2
  35. package/Server/Utils/StartServer.ts +57 -31
  36. package/Server/Utils/WhatsAppTemplateUtil.ts +247 -0
  37. package/Types/Icon/IconProp.ts +1 -0
  38. package/Types/WhatsApp/WhatsAppMessage.ts +12 -0
  39. package/Types/WhatsApp/WhatsAppTemplates.ts +197 -0
  40. package/Types/WhatsAppStatus.ts +8 -0
  41. package/UI/Components/Icon/Icon.tsx +12 -0
  42. package/build/dist/Models/DatabaseModels/GlobalConfig.js +98 -0
  43. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  44. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  45. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  46. package/build/dist/Models/DatabaseModels/Project.js +29 -0
  47. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  48. package/build/dist/Models/DatabaseModels/UserNotificationRule.js +48 -0
  49. package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
  50. package/build/dist/Models/DatabaseModels/UserNotificationSetting.js +18 -0
  51. package/build/dist/Models/DatabaseModels/UserNotificationSetting.js.map +1 -1
  52. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +48 -0
  53. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  54. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +308 -0
  55. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -0
  56. package/build/dist/Models/DatabaseModels/WhatsAppLog.js +911 -0
  57. package/build/dist/Models/DatabaseModels/WhatsAppLog.js.map +1 -0
  58. package/build/dist/Server/API/NotificationAPI.js +2 -2
  59. package/build/dist/Server/API/NotificationAPI.js.map +1 -1
  60. package/build/dist/Server/API/ProjectSSO.js +26 -21
  61. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  62. package/build/dist/Server/API/ShortLinkAPI.js +17 -12
  63. package/build/dist/Server/API/ShortLinkAPI.js.map +1 -1
  64. package/build/dist/Server/API/UserCallAPI.js +54 -44
  65. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  66. package/build/dist/Server/API/UserEmailAPI.js +54 -44
  67. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  68. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +142 -127
  69. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  70. package/build/dist/Server/API/UserPushAPI.js +111 -96
  71. package/build/dist/Server/API/UserPushAPI.js.map +1 -1
  72. package/build/dist/Server/API/UserSmsAPI.js +54 -44
  73. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  74. package/build/dist/Server/API/UserWhatsAppAPI.js +76 -0
  75. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -0
  76. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759838763506-MigrationName.js +41 -0
  77. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759838763506-MigrationName.js.map +1 -0
  78. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759839342566-MigrationName.js +30 -0
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759839342566-MigrationName.js.map +1 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  82. package/build/dist/Server/Services/Index.js +4 -0
  83. package/build/dist/Server/Services/Index.js.map +1 -1
  84. package/build/dist/Server/Services/MonitorService.js +23 -2
  85. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  86. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +29 -6
  87. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  88. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +27 -6
  89. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  90. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +26 -5
  91. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  92. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +34 -3
  93. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  94. package/build/dist/Server/Services/ProbeService.js +12 -1
  95. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  96. package/build/dist/Server/Services/UserNotificationRuleService.js +196 -19
  97. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  98. package/build/dist/Server/Services/UserNotificationSettingService.js +45 -0
  99. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  100. package/build/dist/Server/Services/UserWhatsAppService.js +179 -0
  101. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -0
  102. package/build/dist/Server/Services/WhatsAppLogService.js +13 -0
  103. package/build/dist/Server/Services/WhatsAppLogService.js.map +1 -0
  104. package/build/dist/Server/Services/WhatsAppService.js +103 -0
  105. package/build/dist/Server/Services/WhatsAppService.js.map +1 -0
  106. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +14 -4
  107. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
  108. package/build/dist/Server/Types/Workflow/Components/Webhook.js +2 -2
  109. package/build/dist/Server/Types/Workflow/Components/Webhook.js.map +1 -1
  110. package/build/dist/Server/Utils/StartServer.js +41 -19
  111. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  112. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +124 -0
  113. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -0
  114. package/build/dist/Types/Icon/IconProp.js +1 -0
  115. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  116. package/build/dist/Types/WhatsApp/WhatsAppMessage.js +2 -0
  117. package/build/dist/Types/WhatsApp/WhatsAppMessage.js.map +1 -0
  118. package/build/dist/Types/WhatsApp/WhatsAppTemplates.js +118 -0
  119. package/build/dist/Types/WhatsApp/WhatsAppTemplates.js.map +1 -0
  120. package/build/dist/Types/WhatsAppStatus.js +9 -0
  121. package/build/dist/Types/WhatsAppStatus.js.map +1 -0
  122. package/build/dist/UI/Components/Icon/Icon.js +6 -0
  123. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  124. package/package.json +1 -1
@@ -36,6 +36,8 @@ import DeleteBy from "../Types/Database/DeleteBy";
36
36
  import { OnDelete } from "../Types/Database/Hooks";
37
37
  import PushNotificationMessage from "../../Types/PushNotification/PushNotificationMessage";
38
38
  import PushNotificationUtil from "../Utils/PushNotificationUtil";
39
+ import { createWhatsAppMessageFromTemplate } from "../Utils/WhatsAppTemplateUtil";
40
+ import { WhatsAppMessagePayload } from "../../Types/WhatsApp/WhatsAppMessage";
39
41
 
40
42
  export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
41
43
  private layerUtil = new LayerUtil();
@@ -265,6 +267,19 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
265
267
  requireInteraction: false,
266
268
  });
267
269
 
270
+ const eventType: NotificationSettingEventType =
271
+ NotificationSettingEventType.SEND_WHEN_USER_IS_NO_LONGER_ACTIVE_ON_ON_CALL_ROSTER;
272
+
273
+ const whatsAppMessage: WhatsAppMessagePayload =
274
+ createWhatsAppMessageFromTemplate({
275
+ eventType,
276
+ templateVariables: {
277
+ on_call_policy_name: onCallPolicy.name!,
278
+ schedule_name: onCallSchedule.name!,
279
+ schedule_link: vars["onCallPolicyViewLink"] || "",
280
+ },
281
+ });
282
+
268
283
  await UserNotificationSettingService.sendUserNotification({
269
284
  userId: sendEmailToUserId,
270
285
  projectId: projectId,
@@ -272,8 +287,8 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
272
287
  smsMessage: sms,
273
288
  callRequestMessage: callMessage,
274
289
  pushNotificationMessage: pushMessage,
275
- eventType:
276
- NotificationSettingEventType.SEND_WHEN_USER_IS_NO_LONGER_ACTIVE_ON_ON_CALL_ROSTER,
290
+ whatsAppMessage,
291
+ eventType,
277
292
  onCallPolicyId: escalationRule.onCallDutyPolicy!.id!,
278
293
  onCallPolicyEscalationRuleId:
279
294
  escalationRule.onCallDutyPolicyEscalationRule!.id!,
@@ -385,6 +400,19 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
385
400
  requireInteraction: true,
386
401
  });
387
402
 
403
+ const eventType: NotificationSettingEventType =
404
+ NotificationSettingEventType.SEND_WHEN_USER_IS_ON_CALL_ROSTER;
405
+
406
+ const whatsAppMessage: WhatsAppMessagePayload =
407
+ createWhatsAppMessageFromTemplate({
408
+ eventType,
409
+ templateVariables: {
410
+ on_call_policy_name: onCallPolicy.name!,
411
+ schedule_name: onCallSchedule.name!,
412
+ schedule_link: vars["onCallPolicyViewLink"] || "",
413
+ },
414
+ });
415
+
388
416
  await UserNotificationSettingService.sendUserNotification({
389
417
  userId: sendEmailToUserId,
390
418
  projectId: projectId,
@@ -392,8 +420,8 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
392
420
  smsMessage: sms,
393
421
  callRequestMessage: callMessage,
394
422
  pushNotificationMessage: pushMessage,
395
- eventType:
396
- NotificationSettingEventType.SEND_WHEN_USER_IS_ON_CALL_ROSTER,
423
+ whatsAppMessage,
424
+ eventType,
397
425
  onCallPolicyId: escalationRule.onCallDutyPolicy!.id!,
398
426
  onCallPolicyEscalationRuleId:
399
427
  escalationRule.onCallDutyPolicyEscalationRule!.id!,
@@ -525,6 +553,19 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
525
553
  requireInteraction: false,
526
554
  });
527
555
 
556
+ const eventType: NotificationSettingEventType =
557
+ NotificationSettingEventType.SEND_WHEN_USER_IS_NEXT_ON_CALL_ROSTER;
558
+
559
+ const whatsAppMessage: WhatsAppMessagePayload =
560
+ createWhatsAppMessageFromTemplate({
561
+ eventType,
562
+ templateVariables: {
563
+ on_call_policy_name: onCallPolicy.name!,
564
+ schedule_name: onCallSchedule.name!,
565
+ schedule_link: vars["onCallPolicyViewLink"] || "",
566
+ },
567
+ });
568
+
528
569
  await UserNotificationSettingService.sendUserNotification({
529
570
  userId: sendEmailToUserId,
530
571
  projectId: projectId,
@@ -532,8 +573,8 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
532
573
  smsMessage: sms,
533
574
  callRequestMessage: callMessage,
534
575
  pushNotificationMessage: pushMessage,
535
- eventType:
536
- NotificationSettingEventType.SEND_WHEN_USER_IS_NEXT_ON_CALL_ROSTER,
576
+ whatsAppMessage,
577
+ eventType,
537
578
  onCallPolicyId: escalationRule.onCallDutyPolicy!.id!,
538
579
  onCallPolicyEscalationRuleId:
539
580
  escalationRule.onCallDutyPolicyEscalationRule!.id!,
@@ -33,6 +33,8 @@ import PushNotificationUtil from "../Utils/PushNotificationUtil";
33
33
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
34
34
  import { IsBillingEnabled } from "../EnvironmentConfig";
35
35
  import GlobalCache from "../Infrastructure/GlobalCache";
36
+ import { createWhatsAppMessageFromTemplate } from "../Utils/WhatsAppTemplateUtil";
37
+ import { WhatsAppMessagePayload } from "../../Types/WhatsApp/WhatsAppMessage";
36
38
 
37
39
  export class Service extends DatabaseService<Model> {
38
40
  public constructor() {
@@ -387,6 +389,19 @@ export class Service extends DatabaseService<Model> {
387
389
  pushMessageParams,
388
390
  );
389
391
 
392
+ const eventType: NotificationSettingEventType =
393
+ NotificationSettingEventType.SEND_PROBE_STATUS_CHANGED_OWNER_NOTIFICATION;
394
+
395
+ const whatsAppMessage: WhatsAppMessagePayload =
396
+ createWhatsAppMessageFromTemplate({
397
+ eventType,
398
+ templateVariables: {
399
+ probe_name: probe.name!,
400
+ probe_status: connectionStatus,
401
+ probe_link: vars["viewProbesLink"] || "",
402
+ },
403
+ });
404
+
390
405
  await UserNotificationSettingService.sendUserNotification({
391
406
  userId: user.id!,
392
407
  projectId: probe.projectId!,
@@ -394,8 +409,8 @@ export class Service extends DatabaseService<Model> {
394
409
  smsMessage: sms,
395
410
  callRequestMessage: callMessage,
396
411
  pushNotificationMessage: pushMessage,
397
- eventType:
398
- NotificationSettingEventType.SEND_PROBE_STATUS_CHANGED_OWNER_NOTIFICATION,
412
+ whatsAppMessage,
413
+ eventType,
399
414
  });
400
415
  } catch (e) {
401
416
  logger.error("Error in sending incident created resource notification");
@@ -9,6 +9,7 @@ import IncidentSeverityService from "./IncidentSeverityService";
9
9
  import MailService from "./MailService";
10
10
  import ShortLinkService from "./ShortLinkService";
11
11
  import SmsService from "./SmsService";
12
+ import WhatsAppService from "./WhatsAppService";
12
13
  import UserEmailService from "./UserEmailService";
13
14
  import UserOnCallLogService from "./UserOnCallLogService";
14
15
  import UserOnCallLogTimelineService from "./UserOnCallLogTimelineService";
@@ -29,6 +30,13 @@ import NotificationRuleType from "../../Types/NotificationRule/NotificationRuleT
29
30
  import ObjectID from "../../Types/ObjectID";
30
31
  import Phone from "../../Types/Phone";
31
32
  import SMS from "../../Types/SMS/SMS";
33
+ import WhatsAppMessage from "../../Types/WhatsApp/WhatsAppMessage";
34
+ import {
35
+ renderWhatsAppTemplate,
36
+ WhatsAppTemplateIds,
37
+ WhatsAppTemplateLanguage,
38
+ WhatsAppTemplateId,
39
+ } from "../../Types/WhatsApp/WhatsAppTemplates";
32
40
  import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
33
41
  import UserNotificationExecutionStatus from "../../Types/UserNotification/UserNotificationExecutionStatus";
34
42
  import UserNotificationStatus from "../../Types/UserNotification/UserNotificationStatus";
@@ -135,6 +143,10 @@ export class Service extends DatabaseService<Model> {
135
143
  phone: true,
136
144
  isVerified: true,
137
145
  },
146
+ userWhatsApp: {
147
+ phone: true,
148
+ isVerified: true,
149
+ },
138
150
  userEmail: {
139
151
  email: true,
140
152
  isVerified: true,
@@ -224,6 +236,7 @@ export class Service extends DatabaseService<Model> {
224
236
  name: true,
225
237
  },
226
238
  rootCause: true,
239
+ incidentNumber: true,
227
240
  },
228
241
  });
229
242
  }
@@ -252,6 +265,7 @@ export class Service extends DatabaseService<Model> {
252
265
  alertSeverity: {
253
266
  name: true,
254
267
  },
268
+ alertNumber: true,
255
269
  },
256
270
  });
257
271
  }
@@ -516,6 +530,125 @@ export class Service extends DatabaseService<Model> {
516
530
  });
517
531
  }
518
532
 
533
+ if (
534
+ notificationRuleItem.userWhatsApp?.phone &&
535
+ notificationRuleItem.userWhatsApp?.isVerified
536
+ ) {
537
+ if (
538
+ options.userNotificationEventType ===
539
+ UserNotificationEventType.AlertCreated &&
540
+ alert
541
+ ) {
542
+ logTimelineItem.status = UserNotificationStatus.Sending;
543
+ logTimelineItem.statusMessage = `Sending WhatsApp message to ${notificationRuleItem.userWhatsApp?.phone.toString()}.`;
544
+ logTimelineItem.userWhatsAppId = notificationRuleItem.userWhatsApp.id!;
545
+
546
+ const updatedLog: UserOnCallLogTimeline =
547
+ await UserOnCallLogTimelineService.create({
548
+ data: logTimelineItem,
549
+ props: {
550
+ isRoot: true,
551
+ },
552
+ });
553
+
554
+ const whatsAppMessage: WhatsAppMessage =
555
+ await this.generateWhatsAppTemplateForAlertCreated(
556
+ notificationRuleItem.userWhatsApp.phone,
557
+ alert,
558
+ updatedLog.id!,
559
+ );
560
+
561
+ WhatsAppService.sendWhatsAppMessage(whatsAppMessage, {
562
+ projectId: alert.projectId,
563
+ alertId: alert.id!,
564
+ userOnCallLogTimelineId: updatedLog.id!,
565
+ userId: notificationRuleItem.userId!,
566
+ onCallPolicyId: options.onCallPolicyId,
567
+ onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
568
+ teamId: options.userBelongsToTeamId,
569
+ onCallDutyPolicyExecutionLogTimelineId:
570
+ options.onCallDutyPolicyExecutionLogTimelineId,
571
+ onCallScheduleId: options.onCallScheduleId,
572
+ }).catch(async (err: Error) => {
573
+ await UserOnCallLogTimelineService.updateOneById({
574
+ id: updatedLog.id!,
575
+ data: {
576
+ status: UserNotificationStatus.Error,
577
+ statusMessage: err.message || "Error sending WhatsApp message.",
578
+ },
579
+ props: {
580
+ isRoot: true,
581
+ },
582
+ });
583
+ });
584
+ }
585
+
586
+ if (
587
+ options.userNotificationEventType ===
588
+ UserNotificationEventType.IncidentCreated &&
589
+ incident
590
+ ) {
591
+ logTimelineItem.status = UserNotificationStatus.Sending;
592
+ logTimelineItem.statusMessage = `Sending WhatsApp message to ${notificationRuleItem.userWhatsApp?.phone.toString()}.`;
593
+ logTimelineItem.userWhatsAppId = notificationRuleItem.userWhatsApp.id!;
594
+
595
+ const updatedLog: UserOnCallLogTimeline =
596
+ await UserOnCallLogTimelineService.create({
597
+ data: logTimelineItem,
598
+ props: {
599
+ isRoot: true,
600
+ },
601
+ });
602
+
603
+ const whatsAppMessage: WhatsAppMessage =
604
+ await this.generateWhatsAppTemplateForIncidentCreated(
605
+ notificationRuleItem.userWhatsApp.phone,
606
+ incident,
607
+ updatedLog.id!,
608
+ );
609
+
610
+ WhatsAppService.sendWhatsAppMessage(whatsAppMessage, {
611
+ projectId: incident.projectId,
612
+ incidentId: incident.id!,
613
+ userOnCallLogTimelineId: updatedLog.id!,
614
+ userId: notificationRuleItem.userId!,
615
+ onCallPolicyId: options.onCallPolicyId,
616
+ onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
617
+ teamId: options.userBelongsToTeamId,
618
+ onCallDutyPolicyExecutionLogTimelineId:
619
+ options.onCallDutyPolicyExecutionLogTimelineId,
620
+ onCallScheduleId: options.onCallScheduleId,
621
+ }).catch(async (err: Error) => {
622
+ await UserOnCallLogTimelineService.updateOneById({
623
+ id: updatedLog.id!,
624
+ data: {
625
+ status: UserNotificationStatus.Error,
626
+ statusMessage: err.message || "Error sending WhatsApp message.",
627
+ },
628
+ props: {
629
+ isRoot: true,
630
+ },
631
+ });
632
+ });
633
+ }
634
+ }
635
+
636
+ if (
637
+ notificationRuleItem.userWhatsApp?.phone &&
638
+ !notificationRuleItem.userWhatsApp?.isVerified
639
+ ) {
640
+ logTimelineItem.status = UserNotificationStatus.Error;
641
+ logTimelineItem.statusMessage = `WhatsApp message not sent because phone ${notificationRuleItem.userWhatsApp?.phone.toString()} is not verified.`;
642
+ logTimelineItem.userWhatsAppId = notificationRuleItem.userWhatsApp.id!;
643
+
644
+ await UserOnCallLogTimelineService.create({
645
+ data: logTimelineItem,
646
+ props: {
647
+ isRoot: true,
648
+ },
649
+ });
650
+ }
651
+
519
652
  // send call.
520
653
  if (
521
654
  notificationRuleItem.userCall?.phone &&
@@ -930,11 +1063,14 @@ export class Service extends DatabaseService<Model> {
930
1063
  );
931
1064
  const url: URL = await ShortLinkService.getShortenedUrl(shortUrl);
932
1065
 
1066
+ const alertIdentifier: string =
1067
+ alert.alertNumber !== undefined
1068
+ ? `#${alert.alertNumber} (${alert.title || "Alert"})`
1069
+ : alert.title || "Alert";
1070
+
933
1071
  const sms: SMS = {
934
1072
  to,
935
- message: `This is a message from OneUptime. A new alert has been created. ${
936
- alert.title
937
- }. To acknowledge this alert, please click on the following link ${url.toString()}`,
1073
+ message: `This is a message from OneUptime. A new alert has been created: ${alertIdentifier}. To acknowledge this alert, please click on the following link ${url.toString()}`,
938
1074
  };
939
1075
 
940
1076
  return sms;
@@ -960,16 +1096,129 @@ export class Service extends DatabaseService<Model> {
960
1096
  );
961
1097
  const url: URL = await ShortLinkService.getShortenedUrl(shortUrl);
962
1098
 
1099
+ const incidentIdentifier: string =
1100
+ incident.incidentNumber !== undefined
1101
+ ? `#${incident.incidentNumber} (${incident.title || "Incident"})`
1102
+ : incident.title || "Incident";
1103
+
963
1104
  const sms: SMS = {
964
1105
  to,
965
- message: `This is a message from OneUptime. A new incident has been created. ${
966
- incident.title
967
- }. To acknowledge this incident, please click on the following link ${url.toString()}`,
1106
+ message: `This is a message from OneUptime. A new incident has been created: ${incidentIdentifier}. To acknowledge this incident, please click on the following link ${url.toString()}`,
968
1107
  };
969
1108
 
970
1109
  return sms;
971
1110
  }
972
1111
 
1112
+ @CaptureSpan()
1113
+ public async generateWhatsAppTemplateForAlertCreated(
1114
+ to: Phone,
1115
+ alert: Alert,
1116
+ userOnCallLogTimelineId: ObjectID,
1117
+ ): Promise<WhatsAppMessage> {
1118
+ const host: Hostname = await DatabaseConfig.getHost();
1119
+ const httpProtocol: Protocol = await DatabaseConfig.getHttpProtocol();
1120
+
1121
+ const acknowledgeShortLink: ShortLink =
1122
+ await ShortLinkService.saveShortLinkFor(
1123
+ new URL(
1124
+ httpProtocol,
1125
+ host,
1126
+ new Route(AppApiRoute.toString())
1127
+ .addRoute(new UserOnCallLogTimeline().crudApiPath!)
1128
+ .addRoute("/acknowledge/" + userOnCallLogTimelineId.toString()),
1129
+ ),
1130
+ );
1131
+
1132
+ const acknowledgeUrl: URL =
1133
+ await ShortLinkService.getShortenedUrl(acknowledgeShortLink);
1134
+
1135
+ const alertLinkOnDashboard: string =
1136
+ alert.projectId && alert.id
1137
+ ? (
1138
+ await AlertService.getAlertLinkInDashboard(
1139
+ alert.projectId,
1140
+ alert.id,
1141
+ )
1142
+ ).toString()
1143
+ : acknowledgeUrl.toString();
1144
+
1145
+ const templateKey: WhatsAppTemplateId = WhatsAppTemplateIds.AlertCreated;
1146
+ const templateVariables: Record<string, string> = {
1147
+ project_name: alert.project?.name || "OneUptime",
1148
+ alert_title: alert.title || "",
1149
+ acknowledge_url: acknowledgeUrl.toString(),
1150
+ alert_number:
1151
+ alert.alertNumber !== undefined ? alert.alertNumber.toString() : "",
1152
+ alert_link: alertLinkOnDashboard,
1153
+ };
1154
+
1155
+ const body: string = renderWhatsAppTemplate(templateKey, templateVariables);
1156
+
1157
+ return {
1158
+ to,
1159
+ body,
1160
+ templateKey,
1161
+ templateVariables,
1162
+ templateLanguageCode: WhatsAppTemplateLanguage[templateKey],
1163
+ };
1164
+ }
1165
+
1166
+ @CaptureSpan()
1167
+ public async generateWhatsAppTemplateForIncidentCreated(
1168
+ to: Phone,
1169
+ incident: Incident,
1170
+ userOnCallLogTimelineId: ObjectID,
1171
+ ): Promise<WhatsAppMessage> {
1172
+ const host: Hostname = await DatabaseConfig.getHost();
1173
+ const httpProtocol: Protocol = await DatabaseConfig.getHttpProtocol();
1174
+
1175
+ const acknowledgeShortLink: ShortLink =
1176
+ await ShortLinkService.saveShortLinkFor(
1177
+ new URL(
1178
+ httpProtocol,
1179
+ host,
1180
+ new Route(AppApiRoute.toString())
1181
+ .addRoute(new UserOnCallLogTimeline().crudApiPath!)
1182
+ .addRoute("/acknowledge/" + userOnCallLogTimelineId.toString()),
1183
+ ),
1184
+ );
1185
+
1186
+ const acknowledgeUrl: URL =
1187
+ await ShortLinkService.getShortenedUrl(acknowledgeShortLink);
1188
+
1189
+ const incidentLinkOnDashboard: string =
1190
+ incident.projectId && incident.id
1191
+ ? (
1192
+ await IncidentService.getIncidentLinkInDashboard(
1193
+ incident.projectId,
1194
+ incident.id,
1195
+ )
1196
+ ).toString()
1197
+ : acknowledgeUrl.toString();
1198
+
1199
+ const templateKey: WhatsAppTemplateId = WhatsAppTemplateIds.IncidentCreated;
1200
+ const templateVariables: Record<string, string> = {
1201
+ project_name: incident.project?.name || "OneUptime",
1202
+ incident_title: incident.title || "",
1203
+ acknowledge_url: acknowledgeUrl.toString(),
1204
+ incident_number:
1205
+ incident.incidentNumber !== undefined
1206
+ ? incident.incidentNumber.toString()
1207
+ : "",
1208
+ incident_link: incidentLinkOnDashboard,
1209
+ };
1210
+
1211
+ const body: string = renderWhatsAppTemplate(templateKey, templateVariables);
1212
+
1213
+ return {
1214
+ to,
1215
+ body,
1216
+ templateKey,
1217
+ templateVariables,
1218
+ templateLanguageCode: WhatsAppTemplateLanguage[templateKey],
1219
+ };
1220
+ }
1221
+
973
1222
  @CaptureSpan()
974
1223
  public async generateEmailTemplateForAlertCreated(
975
1224
  to: Email,
@@ -1210,12 +1459,14 @@ export class Service extends DatabaseService<Model> {
1210
1459
  !createBy.data.userEmail &&
1211
1460
  !createBy.data.userSms &&
1212
1461
  !createBy.data.userSmsId &&
1462
+ !createBy.data.userWhatsApp &&
1463
+ !createBy.data.userWhatsAppId &&
1213
1464
  !createBy.data.userEmailId &&
1214
1465
  !createBy.data.userPushId &&
1215
1466
  !createBy.data.userPush
1216
1467
  ) {
1217
1468
  throw new BadDataException(
1218
- "Call, SMS, Email, or Push notification is required",
1469
+ "Call, SMS, WhatsApp, Email, or Push notification is required",
1219
1470
  );
1220
1471
  }
1221
1472
 
@@ -10,6 +10,8 @@ import UserCallService from "./UserCallService";
10
10
  import UserEmailService from "./UserEmailService";
11
11
  import UserSmsService from "./UserSmsService";
12
12
  import PushNotificationService from "./PushNotificationService";
13
+ import UserWhatsAppService from "./UserWhatsAppService";
14
+ import WhatsAppService from "./WhatsAppService";
13
15
  import { CallRequestMessage } from "../../Types/Call/CallRequest";
14
16
  import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
15
17
  import { EmailEnvelope } from "../../Types/Email/EmailMessage";
@@ -19,11 +21,16 @@ import ObjectID from "../../Types/ObjectID";
19
21
  import PositiveNumber from "../../Types/PositiveNumber";
20
22
  import { SMSMessage } from "../../Types/SMS/SMS";
21
23
  import PushNotificationMessage from "../../Types/PushNotification/PushNotificationMessage";
24
+ import WhatsAppMessage, {
25
+ WhatsAppMessagePayload,
26
+ } from "../../Types/WhatsApp/WhatsAppMessage";
22
27
  import UserCall from "../../Models/DatabaseModels/UserCall";
23
28
  import UserEmail from "../../Models/DatabaseModels/UserEmail";
24
29
  import UserNotificationSetting from "../../Models/DatabaseModels/UserNotificationSetting";
25
30
  import UserSMS from "../../Models/DatabaseModels/UserSMS";
31
+ import UserWhatsApp from "../../Models/DatabaseModels/UserWhatsApp";
26
32
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
33
+ import { appendRecipientToWhatsAppMessage } from "../Utils/WhatsAppTemplateUtil";
27
34
 
28
35
  export class Service extends DatabaseService<UserNotificationSetting> {
29
36
  public constructor() {
@@ -39,6 +46,7 @@ export class Service extends DatabaseService<UserNotificationSetting> {
39
46
  smsMessage: SMSMessage;
40
47
  callRequestMessage: CallRequestMessage;
41
48
  pushNotificationMessage: PushNotificationMessage;
49
+ whatsAppMessage: WhatsAppMessagePayload;
42
50
  incidentId?: ObjectID | undefined;
43
51
  alertId?: ObjectID | undefined;
44
52
  scheduledMaintenanceId?: ObjectID | undefined;
@@ -67,6 +75,7 @@ export class Service extends DatabaseService<UserNotificationSetting> {
67
75
  select: {
68
76
  alertByEmail: true,
69
77
  alertBySMS: true,
78
+ alertByWhatsApp: true,
70
79
  alertByCall: true,
71
80
  alertByPush: true,
72
81
  },
@@ -167,6 +176,57 @@ export class Service extends DatabaseService<UserNotificationSetting> {
167
176
  }
168
177
  }
169
178
 
179
+ if (notificationSettings.alertByWhatsApp) {
180
+ const userWhatsApps: Array<UserWhatsApp> =
181
+ await UserWhatsAppService.findBy({
182
+ query: {
183
+ userId: data.userId,
184
+ projectId: data.projectId,
185
+ isVerified: true,
186
+ },
187
+ select: {
188
+ phone: true,
189
+ },
190
+ limit: LIMIT_PER_PROJECT,
191
+ skip: 0,
192
+ props: {
193
+ isRoot: true,
194
+ },
195
+ });
196
+
197
+ if (!data.whatsAppMessage) {
198
+ logger.warn(
199
+ "Skipping WhatsApp notification because WhatsApp template payload is missing.",
200
+ );
201
+ } else {
202
+ for (const userWhatsApp of userWhatsApps) {
203
+ const whatsAppMessage: WhatsAppMessage =
204
+ appendRecipientToWhatsAppMessage(
205
+ data.whatsAppMessage,
206
+ userWhatsApp.phone!,
207
+ );
208
+
209
+ WhatsAppService.sendWhatsAppMessage(whatsAppMessage, {
210
+ projectId: data.projectId,
211
+ incidentId: data.incidentId,
212
+ alertId: data.alertId,
213
+ scheduledMaintenanceId: data.scheduledMaintenanceId,
214
+ statusPageId: data.statusPageId,
215
+ statusPageAnnouncementId: data.statusPageAnnouncementId,
216
+ userId: data.userId,
217
+ teamId: data.teamId,
218
+ onCallPolicyId: data.onCallPolicyId,
219
+ onCallPolicyEscalationRuleId: data.onCallPolicyEscalationRuleId,
220
+ onCallDutyPolicyExecutionLogTimelineId:
221
+ data.onCallDutyPolicyExecutionLogTimelineId,
222
+ onCallScheduleId: data.onCallScheduleId,
223
+ }).catch((err: Error) => {
224
+ logger.error(err);
225
+ });
226
+ }
227
+ }
228
+ }
229
+
170
230
  if (notificationSettings.alertByCall) {
171
231
  const userCalls: Array<UserCall> = await UserCallService.findBy({
172
232
  query: {