@oneuptime/common 9.4.8 → 9.4.11
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.
- package/Models/DatabaseModels/Alert.ts +1 -0
- package/Models/DatabaseModels/AlertFeed.ts +1 -0
- package/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.ts +59 -0
- package/Models/DatabaseModels/UserOnCallLog.ts +48 -0
- package/Models/DatabaseModels/UserOnCallLogTimeline.ts +49 -0
- package/Server/API/UserOnCallLogTimelineAPI.ts +65 -25
- package/Server/Infrastructure/Postgres/SchemaMigrations/1769469813786-MigrationName.ts +71 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1769517677937-RenameNotificationRuleTypes.ts +67 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/AlertEpisodeMemberService.ts +49 -1
- package/Server/Services/AlertEpisodeService.ts +134 -26
- package/Server/Services/AlertGroupingEngineService.ts +3 -168
- package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +18 -1
- package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +64 -2
- package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +27 -1
- package/Server/Services/OnCallDutyPolicyService.ts +11 -1
- package/Server/Services/PushNotificationService.ts +1 -0
- package/Server/Services/UserNotificationRuleService.ts +670 -10
- package/Server/Services/UserOnCallLogService.ts +58 -14
- package/Server/Utils/PushNotificationUtil.ts +75 -16
- package/Types/Database/TableColumn.ts +1 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/NotificationRule/NotificationRuleType.ts +3 -2
- package/Types/WhatsApp/WhatsAppTemplates.ts +4 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +1 -1
- package/Utils/Schema/ModelSchema.ts +2 -0
- package/build/dist/Models/DatabaseModels/Alert.js +1 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertFeed.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js +58 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js +47 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +48 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +55 -15
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769469813786-MigrationName.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769469813786-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769517677937-RenameNotificationRuleTypes.js +67 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769517677937-RenameNotificationRuleTypes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeMemberService.js +43 -1
- package/build/dist/Server/Services/AlertEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeService.js +111 -23
- package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/AlertGroupingEngineService.js +8 -137
- package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +10 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +49 -2
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +21 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyService.js +6 -1
- package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +540 -51
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserOnCallLogService.js +48 -12
- package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
- package/build/dist/Server/Utils/PushNotificationUtil.js +51 -16
- package/build/dist/Server/Utils/PushNotificationUtil.js.map +1 -1
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/NotificationRule/NotificationRuleType.js +3 -2
- package/build/dist/Types/NotificationRule/NotificationRuleType.js.map +1 -1
- package/build/dist/Types/WhatsApp/WhatsAppTemplates.js +3 -0
- package/build/dist/Types/WhatsApp/WhatsAppTemplates.js.map +1 -1
- package/build/dist/Utils/Schema/ModelSchema.js +2 -0
- package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
- package/package.json +1 -1
|
@@ -24,6 +24,7 @@ import { AppApiRoute } from "../../ServiceRoute";
|
|
|
24
24
|
import Route from "../../Types/API/Route";
|
|
25
25
|
import URL from "../../Types/API/URL";
|
|
26
26
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
27
|
+
import QueryHelper from "../Types/Database/QueryHelper";
|
|
27
28
|
import OneUptimeDate from "../../Types/Date";
|
|
28
29
|
import Email from "../../Types/Email";
|
|
29
30
|
import EmailTemplateType from "../../Types/Email/EmailTemplateType";
|
|
@@ -43,6 +44,9 @@ import UserOnCallLogTimeline from "../../Models/DatabaseModels/UserOnCallLogTime
|
|
|
43
44
|
import Alert from "../../Models/DatabaseModels/Alert";
|
|
44
45
|
import AlertService from "./AlertService";
|
|
45
46
|
import AlertSeverityService from "./AlertSeverityService";
|
|
47
|
+
import AlertEpisode from "../../Models/DatabaseModels/AlertEpisode";
|
|
48
|
+
import AlertEpisodeService from "./AlertEpisodeService";
|
|
49
|
+
import AlertEpisodeMemberService from "./AlertEpisodeMemberService";
|
|
46
50
|
import WorkspaceNotificationRuleService from "./WorkspaceNotificationRuleService";
|
|
47
51
|
import PushNotificationService from "./PushNotificationService";
|
|
48
52
|
import NotificationRuleEventType from "../../Types/Workspace/NotificationRules/EventType";
|
|
@@ -55,7 +59,7 @@ export class Service extends DatabaseService {
|
|
|
55
59
|
}
|
|
56
60
|
async executeNotificationRuleItem(userNotificationRuleId, options) {
|
|
57
61
|
// get user notification log and see if this rule has already been executed. If so then skip.
|
|
58
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13;
|
|
62
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20;
|
|
59
63
|
const userOnCallLog = await UserOnCallLogService.findOneById({
|
|
60
64
|
id: options.userNotificationLogId,
|
|
61
65
|
props: {
|
|
@@ -150,6 +154,10 @@ export class Service extends DatabaseService {
|
|
|
150
154
|
if (options.triggeredByAlertId) {
|
|
151
155
|
logTimelineItem.triggeredByAlertId = options.triggeredByAlertId;
|
|
152
156
|
}
|
|
157
|
+
if (options.triggeredByAlertEpisodeId) {
|
|
158
|
+
logTimelineItem.triggeredByAlertEpisodeId =
|
|
159
|
+
options.triggeredByAlertEpisodeId;
|
|
160
|
+
}
|
|
153
161
|
if (options.onCallDutyPolicyExecutionLogTimelineId) {
|
|
154
162
|
logTimelineItem.onCallDutyPolicyExecutionLogTimelineId =
|
|
155
163
|
options.onCallDutyPolicyExecutionLogTimelineId;
|
|
@@ -157,6 +165,7 @@ export class Service extends DatabaseService {
|
|
|
157
165
|
// add status and status message and save.
|
|
158
166
|
let incident = null;
|
|
159
167
|
let alert = null;
|
|
168
|
+
let alertEpisode = null;
|
|
160
169
|
if (options.userNotificationEventType ===
|
|
161
170
|
UserNotificationEventType.IncidentCreated &&
|
|
162
171
|
options.triggeredByIncidentId) {
|
|
@@ -210,8 +219,35 @@ export class Service extends DatabaseService {
|
|
|
210
219
|
},
|
|
211
220
|
});
|
|
212
221
|
}
|
|
213
|
-
if (
|
|
214
|
-
|
|
222
|
+
if (options.userNotificationEventType ===
|
|
223
|
+
UserNotificationEventType.AlertEpisodeCreated &&
|
|
224
|
+
options.triggeredByAlertEpisodeId) {
|
|
225
|
+
alertEpisode = await AlertEpisodeService.findOneById({
|
|
226
|
+
id: options.triggeredByAlertEpisodeId,
|
|
227
|
+
props: {
|
|
228
|
+
isRoot: true,
|
|
229
|
+
},
|
|
230
|
+
select: {
|
|
231
|
+
_id: true,
|
|
232
|
+
title: true,
|
|
233
|
+
description: true,
|
|
234
|
+
projectId: true,
|
|
235
|
+
project: {
|
|
236
|
+
name: true,
|
|
237
|
+
},
|
|
238
|
+
currentAlertState: {
|
|
239
|
+
name: true,
|
|
240
|
+
},
|
|
241
|
+
alertSeverity: {
|
|
242
|
+
name: true,
|
|
243
|
+
},
|
|
244
|
+
episodeNumber: true,
|
|
245
|
+
rootCause: true,
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
if (!incident && !alert && !alertEpisode) {
|
|
250
|
+
throw new BadDataException("Incident, Alert, or Alert Episode not found.");
|
|
215
251
|
}
|
|
216
252
|
if (((_a = notificationRuleItem.userEmail) === null || _a === void 0 ? void 0 : _a.email) &&
|
|
217
253
|
((_b = notificationRuleItem.userEmail) === null || _b === void 0 ? void 0 : _b.isVerified)) {
|
|
@@ -293,13 +329,50 @@ export class Service extends DatabaseService {
|
|
|
293
329
|
});
|
|
294
330
|
});
|
|
295
331
|
}
|
|
332
|
+
// send email for alert episode
|
|
333
|
+
if (options.userNotificationEventType ===
|
|
334
|
+
UserNotificationEventType.AlertEpisodeCreated &&
|
|
335
|
+
alertEpisode) {
|
|
336
|
+
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
337
|
+
logTimelineItem.statusMessage = `Sending email to ${(_g = notificationRuleItem.userEmail) === null || _g === void 0 ? void 0 : _g.email.toString()}`;
|
|
338
|
+
logTimelineItem.userEmailId = notificationRuleItem.userEmail.id;
|
|
339
|
+
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
340
|
+
data: logTimelineItem,
|
|
341
|
+
props: {
|
|
342
|
+
isRoot: true,
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
const emailMessage = await this.generateEmailTemplateForAlertEpisodeCreated((_h = notificationRuleItem.userEmail) === null || _h === void 0 ? void 0 : _h.email, alertEpisode, updatedLog.id);
|
|
346
|
+
MailService.sendMail(emailMessage, {
|
|
347
|
+
userOnCallLogTimelineId: updatedLog.id,
|
|
348
|
+
projectId: options.projectId,
|
|
349
|
+
alertEpisodeId: alertEpisode.id,
|
|
350
|
+
userId: notificationRuleItem.userId,
|
|
351
|
+
onCallPolicyId: options.onCallPolicyId,
|
|
352
|
+
onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
|
|
353
|
+
teamId: options.userBelongsToTeamId,
|
|
354
|
+
onCallDutyPolicyExecutionLogTimelineId: options.onCallDutyPolicyExecutionLogTimelineId,
|
|
355
|
+
onCallScheduleId: options.onCallScheduleId,
|
|
356
|
+
}).catch(async (err) => {
|
|
357
|
+
await UserOnCallLogTimelineService.updateOneById({
|
|
358
|
+
id: updatedLog.id,
|
|
359
|
+
data: {
|
|
360
|
+
status: UserNotificationStatus.Error,
|
|
361
|
+
statusMessage: err.message || "Error sending email.",
|
|
362
|
+
},
|
|
363
|
+
props: {
|
|
364
|
+
isRoot: true,
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
}
|
|
296
369
|
}
|
|
297
370
|
// if you have an email but is not verified, then create a log.
|
|
298
|
-
if (((
|
|
299
|
-
!((
|
|
371
|
+
if (((_j = notificationRuleItem.userEmail) === null || _j === void 0 ? void 0 : _j.email) &&
|
|
372
|
+
!((_k = notificationRuleItem.userEmail) === null || _k === void 0 ? void 0 : _k.isVerified)) {
|
|
300
373
|
// create an error log.
|
|
301
374
|
logTimelineItem.status = UserNotificationStatus.Error;
|
|
302
|
-
logTimelineItem.statusMessage = `Email notification not sent because email ${(
|
|
375
|
+
logTimelineItem.statusMessage = `Email notification not sent because email ${(_l = notificationRuleItem.userEmail) === null || _l === void 0 ? void 0 : _l.email.toString()} is not verified.`;
|
|
303
376
|
await UserOnCallLogTimelineService.create({
|
|
304
377
|
data: logTimelineItem,
|
|
305
378
|
props: {
|
|
@@ -308,15 +381,15 @@ export class Service extends DatabaseService {
|
|
|
308
381
|
});
|
|
309
382
|
}
|
|
310
383
|
// send sms.
|
|
311
|
-
if (((
|
|
312
|
-
((
|
|
384
|
+
if (((_m = notificationRuleItem.userSms) === null || _m === void 0 ? void 0 : _m.phone) &&
|
|
385
|
+
((_o = notificationRuleItem.userSms) === null || _o === void 0 ? void 0 : _o.isVerified)) {
|
|
313
386
|
//send sms for alert
|
|
314
387
|
if (options.userNotificationEventType ===
|
|
315
388
|
UserNotificationEventType.AlertCreated &&
|
|
316
389
|
alert) {
|
|
317
390
|
// create an error log.
|
|
318
391
|
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
319
|
-
logTimelineItem.statusMessage = `Sending SMS to ${(
|
|
392
|
+
logTimelineItem.statusMessage = `Sending SMS to ${(_p = notificationRuleItem.userSms) === null || _p === void 0 ? void 0 : _p.phone.toString()}.`;
|
|
320
393
|
logTimelineItem.userSmsId = notificationRuleItem.userSms.id;
|
|
321
394
|
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
322
395
|
data: logTimelineItem,
|
|
@@ -355,7 +428,7 @@ export class Service extends DatabaseService {
|
|
|
355
428
|
incident) {
|
|
356
429
|
// create an error log.
|
|
357
430
|
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
358
|
-
logTimelineItem.statusMessage = `Sending SMS to ${(
|
|
431
|
+
logTimelineItem.statusMessage = `Sending SMS to ${(_q = notificationRuleItem.userSms) === null || _q === void 0 ? void 0 : _q.phone.toString()}.`;
|
|
359
432
|
logTimelineItem.userSmsId = notificationRuleItem.userSms.id;
|
|
360
433
|
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
361
434
|
data: logTimelineItem,
|
|
@@ -388,12 +461,49 @@ export class Service extends DatabaseService {
|
|
|
388
461
|
});
|
|
389
462
|
});
|
|
390
463
|
}
|
|
464
|
+
// send sms for alert episode
|
|
465
|
+
if (options.userNotificationEventType ===
|
|
466
|
+
UserNotificationEventType.AlertEpisodeCreated &&
|
|
467
|
+
alertEpisode) {
|
|
468
|
+
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
469
|
+
logTimelineItem.statusMessage = `Sending SMS to ${(_r = notificationRuleItem.userSms) === null || _r === void 0 ? void 0 : _r.phone.toString()}.`;
|
|
470
|
+
logTimelineItem.userSmsId = notificationRuleItem.userSms.id;
|
|
471
|
+
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
472
|
+
data: logTimelineItem,
|
|
473
|
+
props: {
|
|
474
|
+
isRoot: true,
|
|
475
|
+
},
|
|
476
|
+
});
|
|
477
|
+
const smsMessage = await this.generateSmsTemplateForAlertEpisodeCreated(notificationRuleItem.userSms.phone, alertEpisode, updatedLog.id);
|
|
478
|
+
SmsService.sendSms(smsMessage, {
|
|
479
|
+
projectId: alertEpisode.projectId,
|
|
480
|
+
userOnCallLogTimelineId: updatedLog.id,
|
|
481
|
+
alertEpisodeId: alertEpisode.id,
|
|
482
|
+
userId: notificationRuleItem.userId,
|
|
483
|
+
onCallPolicyId: options.onCallPolicyId,
|
|
484
|
+
onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
|
|
485
|
+
teamId: options.userBelongsToTeamId,
|
|
486
|
+
onCallDutyPolicyExecutionLogTimelineId: options.onCallDutyPolicyExecutionLogTimelineId,
|
|
487
|
+
onCallScheduleId: options.onCallScheduleId,
|
|
488
|
+
}).catch(async (err) => {
|
|
489
|
+
await UserOnCallLogTimelineService.updateOneById({
|
|
490
|
+
id: updatedLog.id,
|
|
491
|
+
data: {
|
|
492
|
+
status: UserNotificationStatus.Error,
|
|
493
|
+
statusMessage: err.message || "Error sending SMS.",
|
|
494
|
+
},
|
|
495
|
+
props: {
|
|
496
|
+
isRoot: true,
|
|
497
|
+
},
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
}
|
|
391
501
|
}
|
|
392
|
-
if (((
|
|
393
|
-
!((
|
|
502
|
+
if (((_s = notificationRuleItem.userSms) === null || _s === void 0 ? void 0 : _s.phone) &&
|
|
503
|
+
!((_t = notificationRuleItem.userSms) === null || _t === void 0 ? void 0 : _t.isVerified)) {
|
|
394
504
|
// create a log.
|
|
395
505
|
logTimelineItem.status = UserNotificationStatus.Error;
|
|
396
|
-
logTimelineItem.statusMessage = `SMS not sent because phone ${(
|
|
506
|
+
logTimelineItem.statusMessage = `SMS not sent because phone ${(_u = notificationRuleItem.userSms) === null || _u === void 0 ? void 0 : _u.phone.toString()} is not verified.`;
|
|
397
507
|
await UserOnCallLogTimelineService.create({
|
|
398
508
|
data: logTimelineItem,
|
|
399
509
|
props: {
|
|
@@ -401,13 +511,13 @@ export class Service extends DatabaseService {
|
|
|
401
511
|
},
|
|
402
512
|
});
|
|
403
513
|
}
|
|
404
|
-
if (((
|
|
405
|
-
((
|
|
514
|
+
if (((_v = notificationRuleItem.userWhatsApp) === null || _v === void 0 ? void 0 : _v.phone) &&
|
|
515
|
+
((_w = notificationRuleItem.userWhatsApp) === null || _w === void 0 ? void 0 : _w.isVerified)) {
|
|
406
516
|
if (options.userNotificationEventType ===
|
|
407
517
|
UserNotificationEventType.AlertCreated &&
|
|
408
518
|
alert) {
|
|
409
519
|
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
410
|
-
logTimelineItem.statusMessage = `Sending WhatsApp message to ${(
|
|
520
|
+
logTimelineItem.statusMessage = `Sending WhatsApp message to ${(_x = notificationRuleItem.userWhatsApp) === null || _x === void 0 ? void 0 : _x.phone.toString()}.`;
|
|
411
521
|
logTimelineItem.userWhatsAppId = notificationRuleItem.userWhatsApp.id;
|
|
412
522
|
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
413
523
|
data: logTimelineItem,
|
|
@@ -443,7 +553,7 @@ export class Service extends DatabaseService {
|
|
|
443
553
|
UserNotificationEventType.IncidentCreated &&
|
|
444
554
|
incident) {
|
|
445
555
|
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
446
|
-
logTimelineItem.statusMessage = `Sending WhatsApp message to ${(
|
|
556
|
+
logTimelineItem.statusMessage = `Sending WhatsApp message to ${(_y = notificationRuleItem.userWhatsApp) === null || _y === void 0 ? void 0 : _y.phone.toString()}.`;
|
|
447
557
|
logTimelineItem.userWhatsAppId = notificationRuleItem.userWhatsApp.id;
|
|
448
558
|
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
449
559
|
data: logTimelineItem,
|
|
@@ -475,11 +585,48 @@ export class Service extends DatabaseService {
|
|
|
475
585
|
});
|
|
476
586
|
});
|
|
477
587
|
}
|
|
588
|
+
// send WhatsApp for alert episode
|
|
589
|
+
if (options.userNotificationEventType ===
|
|
590
|
+
UserNotificationEventType.AlertEpisodeCreated &&
|
|
591
|
+
alertEpisode) {
|
|
592
|
+
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
593
|
+
logTimelineItem.statusMessage = `Sending WhatsApp message to ${(_z = notificationRuleItem.userWhatsApp) === null || _z === void 0 ? void 0 : _z.phone.toString()}.`;
|
|
594
|
+
logTimelineItem.userWhatsAppId = notificationRuleItem.userWhatsApp.id;
|
|
595
|
+
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
596
|
+
data: logTimelineItem,
|
|
597
|
+
props: {
|
|
598
|
+
isRoot: true,
|
|
599
|
+
},
|
|
600
|
+
});
|
|
601
|
+
const whatsAppMessage = await this.generateWhatsAppTemplateForAlertEpisodeCreated(notificationRuleItem.userWhatsApp.phone, alertEpisode, updatedLog.id);
|
|
602
|
+
WhatsAppService.sendWhatsAppMessage(whatsAppMessage, {
|
|
603
|
+
projectId: alertEpisode.projectId,
|
|
604
|
+
alertEpisodeId: alertEpisode.id,
|
|
605
|
+
userOnCallLogTimelineId: updatedLog.id,
|
|
606
|
+
userId: notificationRuleItem.userId,
|
|
607
|
+
onCallPolicyId: options.onCallPolicyId,
|
|
608
|
+
onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
|
|
609
|
+
teamId: options.userBelongsToTeamId,
|
|
610
|
+
onCallDutyPolicyExecutionLogTimelineId: options.onCallDutyPolicyExecutionLogTimelineId,
|
|
611
|
+
onCallScheduleId: options.onCallScheduleId,
|
|
612
|
+
}).catch(async (err) => {
|
|
613
|
+
await UserOnCallLogTimelineService.updateOneById({
|
|
614
|
+
id: updatedLog.id,
|
|
615
|
+
data: {
|
|
616
|
+
status: UserNotificationStatus.Error,
|
|
617
|
+
statusMessage: err.message || "Error sending WhatsApp message.",
|
|
618
|
+
},
|
|
619
|
+
props: {
|
|
620
|
+
isRoot: true,
|
|
621
|
+
},
|
|
622
|
+
});
|
|
623
|
+
});
|
|
624
|
+
}
|
|
478
625
|
}
|
|
479
|
-
if (((
|
|
480
|
-
!((
|
|
626
|
+
if (((_0 = notificationRuleItem.userWhatsApp) === null || _0 === void 0 ? void 0 : _0.phone) &&
|
|
627
|
+
!((_1 = notificationRuleItem.userWhatsApp) === null || _1 === void 0 ? void 0 : _1.isVerified)) {
|
|
481
628
|
logTimelineItem.status = UserNotificationStatus.Error;
|
|
482
|
-
logTimelineItem.statusMessage = `WhatsApp message not sent because phone ${(
|
|
629
|
+
logTimelineItem.statusMessage = `WhatsApp message not sent because phone ${(_2 = notificationRuleItem.userWhatsApp) === null || _2 === void 0 ? void 0 : _2.phone.toString()} is not verified.`;
|
|
483
630
|
logTimelineItem.userWhatsAppId = notificationRuleItem.userWhatsApp.id;
|
|
484
631
|
await UserOnCallLogTimelineService.create({
|
|
485
632
|
data: logTimelineItem,
|
|
@@ -489,15 +636,15 @@ export class Service extends DatabaseService {
|
|
|
489
636
|
});
|
|
490
637
|
}
|
|
491
638
|
// send call.
|
|
492
|
-
if (((
|
|
493
|
-
((
|
|
639
|
+
if (((_3 = notificationRuleItem.userCall) === null || _3 === void 0 ? void 0 : _3.phone) &&
|
|
640
|
+
((_4 = notificationRuleItem.userCall) === null || _4 === void 0 ? void 0 : _4.isVerified)) {
|
|
494
641
|
// send call for alert
|
|
495
642
|
if (options.userNotificationEventType ===
|
|
496
643
|
UserNotificationEventType.AlertCreated &&
|
|
497
644
|
alert) {
|
|
498
645
|
// create an error log.
|
|
499
646
|
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
500
|
-
logTimelineItem.statusMessage = `Making a call to ${(
|
|
647
|
+
logTimelineItem.statusMessage = `Making a call to ${(_5 = notificationRuleItem.userCall) === null || _5 === void 0 ? void 0 : _5.phone.toString()}.`;
|
|
501
648
|
logTimelineItem.userCallId = notificationRuleItem.userCall.id;
|
|
502
649
|
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
503
650
|
data: logTimelineItem,
|
|
@@ -505,7 +652,7 @@ export class Service extends DatabaseService {
|
|
|
505
652
|
isRoot: true,
|
|
506
653
|
},
|
|
507
654
|
});
|
|
508
|
-
const callRequest = await this.generateCallTemplateForAlertCreated((
|
|
655
|
+
const callRequest = await this.generateCallTemplateForAlertCreated((_6 = notificationRuleItem.userCall) === null || _6 === void 0 ? void 0 : _6.phone, alert, updatedLog.id);
|
|
509
656
|
// send call.
|
|
510
657
|
CallService.makeCall(callRequest, {
|
|
511
658
|
projectId: alert.projectId,
|
|
@@ -535,7 +682,7 @@ export class Service extends DatabaseService {
|
|
|
535
682
|
incident) {
|
|
536
683
|
// send call for incident
|
|
537
684
|
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
538
|
-
logTimelineItem.statusMessage = `Making a call to ${(
|
|
685
|
+
logTimelineItem.statusMessage = `Making a call to ${(_7 = notificationRuleItem.userCall) === null || _7 === void 0 ? void 0 : _7.phone.toString()}.`;
|
|
539
686
|
logTimelineItem.userCallId = notificationRuleItem.userCall.id;
|
|
540
687
|
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
541
688
|
data: logTimelineItem,
|
|
@@ -543,7 +690,7 @@ export class Service extends DatabaseService {
|
|
|
543
690
|
isRoot: true,
|
|
544
691
|
},
|
|
545
692
|
});
|
|
546
|
-
const callRequest = await this.generateCallTemplateForIncidentCreated((
|
|
693
|
+
const callRequest = await this.generateCallTemplateForIncidentCreated((_8 = notificationRuleItem.userCall) === null || _8 === void 0 ? void 0 : _8.phone, incident, updatedLog.id);
|
|
547
694
|
// send call.
|
|
548
695
|
CallService.makeCall(callRequest, {
|
|
549
696
|
projectId: incident.projectId,
|
|
@@ -568,12 +715,49 @@ export class Service extends DatabaseService {
|
|
|
568
715
|
});
|
|
569
716
|
});
|
|
570
717
|
}
|
|
718
|
+
// send call for alert episode
|
|
719
|
+
if (options.userNotificationEventType ===
|
|
720
|
+
UserNotificationEventType.AlertEpisodeCreated &&
|
|
721
|
+
alertEpisode) {
|
|
722
|
+
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
723
|
+
logTimelineItem.statusMessage = `Making a call to ${(_9 = notificationRuleItem.userCall) === null || _9 === void 0 ? void 0 : _9.phone.toString()}.`;
|
|
724
|
+
logTimelineItem.userCallId = notificationRuleItem.userCall.id;
|
|
725
|
+
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
726
|
+
data: logTimelineItem,
|
|
727
|
+
props: {
|
|
728
|
+
isRoot: true,
|
|
729
|
+
},
|
|
730
|
+
});
|
|
731
|
+
const callRequest = await this.generateCallTemplateForAlertEpisodeCreated((_10 = notificationRuleItem.userCall) === null || _10 === void 0 ? void 0 : _10.phone, alertEpisode, updatedLog.id);
|
|
732
|
+
CallService.makeCall(callRequest, {
|
|
733
|
+
projectId: alertEpisode.projectId,
|
|
734
|
+
userOnCallLogTimelineId: updatedLog.id,
|
|
735
|
+
alertEpisodeId: alertEpisode.id,
|
|
736
|
+
userId: notificationRuleItem.userId,
|
|
737
|
+
onCallPolicyId: options.onCallPolicyId,
|
|
738
|
+
onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
|
|
739
|
+
teamId: options.userBelongsToTeamId,
|
|
740
|
+
onCallDutyPolicyExecutionLogTimelineId: options.onCallDutyPolicyExecutionLogTimelineId,
|
|
741
|
+
onCallScheduleId: options.onCallScheduleId,
|
|
742
|
+
}).catch(async (err) => {
|
|
743
|
+
await UserOnCallLogTimelineService.updateOneById({
|
|
744
|
+
id: updatedLog.id,
|
|
745
|
+
data: {
|
|
746
|
+
status: UserNotificationStatus.Error,
|
|
747
|
+
statusMessage: err.message || "Error making call.",
|
|
748
|
+
},
|
|
749
|
+
props: {
|
|
750
|
+
isRoot: true,
|
|
751
|
+
},
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
}
|
|
571
755
|
}
|
|
572
|
-
if (((
|
|
573
|
-
!((
|
|
756
|
+
if (((_11 = notificationRuleItem.userCall) === null || _11 === void 0 ? void 0 : _11.phone) &&
|
|
757
|
+
!((_12 = notificationRuleItem.userCall) === null || _12 === void 0 ? void 0 : _12.isVerified)) {
|
|
574
758
|
// create a log.
|
|
575
759
|
logTimelineItem.status = UserNotificationStatus.Error;
|
|
576
|
-
logTimelineItem.statusMessage = `Call not sent because phone ${(
|
|
760
|
+
logTimelineItem.statusMessage = `Call not sent because phone ${(_13 = notificationRuleItem.userCall) === null || _13 === void 0 ? void 0 : _13.phone.toString()} is not verified.`;
|
|
577
761
|
await UserOnCallLogTimelineService.create({
|
|
578
762
|
data: logTimelineItem,
|
|
579
763
|
props: {
|
|
@@ -582,8 +766,8 @@ export class Service extends DatabaseService {
|
|
|
582
766
|
});
|
|
583
767
|
}
|
|
584
768
|
// send push notification.
|
|
585
|
-
if (((
|
|
586
|
-
((
|
|
769
|
+
if (((_14 = notificationRuleItem.userPush) === null || _14 === void 0 ? void 0 : _14.deviceToken) &&
|
|
770
|
+
((_15 = notificationRuleItem.userPush) === null || _15 === void 0 ? void 0 : _15.isVerified)) {
|
|
587
771
|
// send push notification for alert
|
|
588
772
|
if (options.userNotificationEventType ===
|
|
589
773
|
UserNotificationEventType.AlertCreated &&
|
|
@@ -598,11 +782,9 @@ export class Service extends DatabaseService {
|
|
|
598
782
|
isRoot: true,
|
|
599
783
|
},
|
|
600
784
|
});
|
|
601
|
-
const pushMessage = PushNotificationUtil.createAlertCreatedNotification({
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
alertViewLink: (await AlertService.getAlertLinkInDashboard(alert.projectId, alert.id)).toString(),
|
|
605
|
-
});
|
|
785
|
+
const pushMessage = PushNotificationUtil.createAlertCreatedNotification(Object.assign({ alertTitle: alert.title, projectName: ((_16 = alert.project) === null || _16 === void 0 ? void 0 : _16.name) || "OneUptime", alertViewLink: (await AlertService.getAlertLinkInDashboard(alert.projectId, alert.id)).toString() }, (alert.alertNumber !== undefined && {
|
|
786
|
+
alertNumber: alert.alertNumber,
|
|
787
|
+
})));
|
|
606
788
|
// send push notification.
|
|
607
789
|
PushNotificationService.sendPushNotification({
|
|
608
790
|
devices: [
|
|
@@ -649,11 +831,9 @@ export class Service extends DatabaseService {
|
|
|
649
831
|
isRoot: true,
|
|
650
832
|
},
|
|
651
833
|
});
|
|
652
|
-
const pushMessage = PushNotificationUtil.createIncidentCreatedNotification({
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
incidentViewLink: (await IncidentService.getIncidentLinkInDashboard(incident.projectId, incident.id)).toString(),
|
|
656
|
-
});
|
|
834
|
+
const pushMessage = PushNotificationUtil.createIncidentCreatedNotification(Object.assign({ incidentTitle: incident.title, projectName: ((_17 = incident.project) === null || _17 === void 0 ? void 0 : _17.name) || "OneUptime", incidentViewLink: (await IncidentService.getIncidentLinkInDashboard(incident.projectId, incident.id)).toString() }, (incident.incidentNumber !== undefined && {
|
|
835
|
+
incidentNumber: incident.incidentNumber,
|
|
836
|
+
})));
|
|
657
837
|
// send push notification.
|
|
658
838
|
PushNotificationService.sendPushNotification({
|
|
659
839
|
devices: [
|
|
@@ -686,9 +866,56 @@ export class Service extends DatabaseService {
|
|
|
686
866
|
});
|
|
687
867
|
});
|
|
688
868
|
}
|
|
869
|
+
// send push notification for alert episode
|
|
870
|
+
if (options.userNotificationEventType ===
|
|
871
|
+
UserNotificationEventType.AlertEpisodeCreated &&
|
|
872
|
+
alertEpisode) {
|
|
873
|
+
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
874
|
+
logTimelineItem.statusMessage = `Sending push notification to device.`;
|
|
875
|
+
logTimelineItem.userPushId = notificationRuleItem.userPush.id;
|
|
876
|
+
const updatedLog = await UserOnCallLogTimelineService.create({
|
|
877
|
+
data: logTimelineItem,
|
|
878
|
+
props: {
|
|
879
|
+
isRoot: true,
|
|
880
|
+
},
|
|
881
|
+
});
|
|
882
|
+
const pushMessage = PushNotificationUtil.createAlertEpisodeCreatedNotification(Object.assign({ alertEpisodeTitle: alertEpisode.title, projectName: ((_18 = alertEpisode.project) === null || _18 === void 0 ? void 0 : _18.name) || "OneUptime", alertEpisodeViewLink: (await AlertEpisodeService.getEpisodeLinkInDashboard(alertEpisode.projectId, alertEpisode.id)).toString() }, (alertEpisode.episodeNumber !== undefined && {
|
|
883
|
+
episodeNumber: alertEpisode.episodeNumber,
|
|
884
|
+
})));
|
|
885
|
+
PushNotificationService.sendPushNotification({
|
|
886
|
+
devices: [
|
|
887
|
+
Object.assign({ token: notificationRuleItem.userPush.deviceToken }, (notificationRuleItem.userPush.deviceName && {
|
|
888
|
+
name: notificationRuleItem.userPush.deviceName,
|
|
889
|
+
})),
|
|
890
|
+
],
|
|
891
|
+
message: pushMessage,
|
|
892
|
+
deviceType: notificationRuleItem.userPush.deviceType,
|
|
893
|
+
}, {
|
|
894
|
+
projectId: options.projectId,
|
|
895
|
+
userOnCallLogTimelineId: updatedLog.id,
|
|
896
|
+
alertEpisodeId: alertEpisode.id,
|
|
897
|
+
userId: notificationRuleItem.userId,
|
|
898
|
+
onCallPolicyId: options.onCallPolicyId,
|
|
899
|
+
onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
|
|
900
|
+
teamId: options.userBelongsToTeamId,
|
|
901
|
+
onCallDutyPolicyExecutionLogTimelineId: options.onCallDutyPolicyExecutionLogTimelineId,
|
|
902
|
+
onCallScheduleId: options.onCallScheduleId,
|
|
903
|
+
}).catch(async (err) => {
|
|
904
|
+
await UserOnCallLogTimelineService.updateOneById({
|
|
905
|
+
id: updatedLog.id,
|
|
906
|
+
data: {
|
|
907
|
+
status: UserNotificationStatus.Error,
|
|
908
|
+
statusMessage: err.message || "Error sending push notification.",
|
|
909
|
+
},
|
|
910
|
+
props: {
|
|
911
|
+
isRoot: true,
|
|
912
|
+
},
|
|
913
|
+
});
|
|
914
|
+
});
|
|
915
|
+
}
|
|
689
916
|
}
|
|
690
|
-
if (((
|
|
691
|
-
!((
|
|
917
|
+
if (((_19 = notificationRuleItem.userPush) === null || _19 === void 0 ? void 0 : _19.deviceToken) &&
|
|
918
|
+
!((_20 = notificationRuleItem.userPush) === null || _20 === void 0 ? void 0 : _20.isVerified)) {
|
|
692
919
|
// create a log.
|
|
693
920
|
logTimelineItem.status = UserNotificationStatus.Error;
|
|
694
921
|
logTimelineItem.statusMessage = `Push notification not sent because device is not verified.`;
|
|
@@ -703,6 +930,9 @@ export class Service extends DatabaseService {
|
|
|
703
930
|
async generateCallTemplateForAlertCreated(to, alert, userOnCallLogTimelineId) {
|
|
704
931
|
const host = await DatabaseConfig.getHost();
|
|
705
932
|
const httpProtocol = await DatabaseConfig.getHttpProtocol();
|
|
933
|
+
const alertIdentifier = alert.alertNumber !== undefined
|
|
934
|
+
? `Alert number ${alert.alertNumber}, ${alert.title || "Alert"}`
|
|
935
|
+
: alert.title || "Alert";
|
|
706
936
|
const callRequest = {
|
|
707
937
|
to: to,
|
|
708
938
|
data: [
|
|
@@ -713,7 +943,7 @@ export class Service extends DatabaseService {
|
|
|
713
943
|
sayMessage: "A new alert has been created",
|
|
714
944
|
},
|
|
715
945
|
{
|
|
716
|
-
sayMessage:
|
|
946
|
+
sayMessage: alertIdentifier,
|
|
717
947
|
},
|
|
718
948
|
{
|
|
719
949
|
introMessage: "To acknowledge this alert press 1",
|
|
@@ -739,6 +969,9 @@ export class Service extends DatabaseService {
|
|
|
739
969
|
async generateCallTemplateForIncidentCreated(to, incident, userOnCallLogTimelineId) {
|
|
740
970
|
const host = await DatabaseConfig.getHost();
|
|
741
971
|
const httpProtocol = await DatabaseConfig.getHttpProtocol();
|
|
972
|
+
const incidentIdentifier = incident.incidentNumber !== undefined
|
|
973
|
+
? `Incident number ${incident.incidentNumber}, ${incident.title || "Incident"}`
|
|
974
|
+
: incident.title || "Incident";
|
|
742
975
|
const callRequest = {
|
|
743
976
|
to: to,
|
|
744
977
|
data: [
|
|
@@ -749,7 +982,7 @@ export class Service extends DatabaseService {
|
|
|
749
982
|
sayMessage: "A new incident has been created",
|
|
750
983
|
},
|
|
751
984
|
{
|
|
752
|
-
sayMessage:
|
|
985
|
+
sayMessage: incidentIdentifier,
|
|
753
986
|
},
|
|
754
987
|
{
|
|
755
988
|
introMessage: "To acknowledge this incident press 1",
|
|
@@ -772,6 +1005,45 @@ export class Service extends DatabaseService {
|
|
|
772
1005
|
};
|
|
773
1006
|
return callRequest;
|
|
774
1007
|
}
|
|
1008
|
+
async generateCallTemplateForAlertEpisodeCreated(to, alertEpisode, userOnCallLogTimelineId) {
|
|
1009
|
+
const host = await DatabaseConfig.getHost();
|
|
1010
|
+
const httpProtocol = await DatabaseConfig.getHttpProtocol();
|
|
1011
|
+
const episodeIdentifier = alertEpisode.episodeNumber !== undefined
|
|
1012
|
+
? `Alert episode number ${alertEpisode.episodeNumber}, ${alertEpisode.title || "Alert Episode"}`
|
|
1013
|
+
: alertEpisode.title || "Alert Episode";
|
|
1014
|
+
const callRequest = {
|
|
1015
|
+
to: to,
|
|
1016
|
+
data: [
|
|
1017
|
+
{
|
|
1018
|
+
sayMessage: "This is a call from OneUptime",
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
sayMessage: "A new alert episode has been created",
|
|
1022
|
+
},
|
|
1023
|
+
{
|
|
1024
|
+
sayMessage: episodeIdentifier,
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
introMessage: "To acknowledge this alert episode press 1",
|
|
1028
|
+
numDigits: 1,
|
|
1029
|
+
timeoutInSeconds: 10,
|
|
1030
|
+
noInputMessage: "You have not entered any input. Good bye",
|
|
1031
|
+
onInputCallRequest: {
|
|
1032
|
+
"1": {
|
|
1033
|
+
sayMessage: "You have acknowledged this alert episode. Good bye",
|
|
1034
|
+
},
|
|
1035
|
+
default: {
|
|
1036
|
+
sayMessage: "Invalid input. Good bye",
|
|
1037
|
+
},
|
|
1038
|
+
},
|
|
1039
|
+
responseUrl: new URL(httpProtocol, host, new Route(AppApiRoute.toString())
|
|
1040
|
+
.addRoute(new UserOnCallLogTimeline().crudApiPath)
|
|
1041
|
+
.addRoute("/call/gather-input/" + userOnCallLogTimelineId.toString())),
|
|
1042
|
+
},
|
|
1043
|
+
],
|
|
1044
|
+
};
|
|
1045
|
+
return callRequest;
|
|
1046
|
+
}
|
|
775
1047
|
async generateSmsTemplateForAlertCreated(to, alert, userOnCallLogTimelineId) {
|
|
776
1048
|
const host = await DatabaseConfig.getHost();
|
|
777
1049
|
const httpProtocol = await DatabaseConfig.getHttpProtocol();
|
|
@@ -804,6 +1076,22 @@ export class Service extends DatabaseService {
|
|
|
804
1076
|
};
|
|
805
1077
|
return sms;
|
|
806
1078
|
}
|
|
1079
|
+
async generateSmsTemplateForAlertEpisodeCreated(to, alertEpisode, userOnCallLogTimelineId) {
|
|
1080
|
+
const host = await DatabaseConfig.getHost();
|
|
1081
|
+
const httpProtocol = await DatabaseConfig.getHttpProtocol();
|
|
1082
|
+
const shortUrl = await ShortLinkService.saveShortLinkFor(new URL(httpProtocol, host, new Route(AppApiRoute.toString())
|
|
1083
|
+
.addRoute(new UserOnCallLogTimeline().crudApiPath)
|
|
1084
|
+
.addRoute("/acknowledge-page/" + userOnCallLogTimelineId.toString())));
|
|
1085
|
+
const url = await ShortLinkService.getShortenedUrl(shortUrl);
|
|
1086
|
+
const episodeIdentifier = alertEpisode.episodeNumber !== undefined
|
|
1087
|
+
? `#${alertEpisode.episodeNumber} (${alertEpisode.title || "Alert Episode"})`
|
|
1088
|
+
: alertEpisode.title || "Alert Episode";
|
|
1089
|
+
const sms = {
|
|
1090
|
+
to,
|
|
1091
|
+
message: `This is a message from OneUptime. A new alert episode has been created: ${episodeIdentifier}. To acknowledge this alert episode, please click on the following link ${url.toString()}`,
|
|
1092
|
+
};
|
|
1093
|
+
return sms;
|
|
1094
|
+
}
|
|
807
1095
|
async generateWhatsAppTemplateForAlertCreated(to, alert, userOnCallLogTimelineId) {
|
|
808
1096
|
var _a;
|
|
809
1097
|
const host = await DatabaseConfig.getHost();
|
|
@@ -862,11 +1150,45 @@ export class Service extends DatabaseService {
|
|
|
862
1150
|
templateLanguageCode: WhatsAppTemplateLanguage[templateKey],
|
|
863
1151
|
};
|
|
864
1152
|
}
|
|
1153
|
+
async generateWhatsAppTemplateForAlertEpisodeCreated(to, alertEpisode, userOnCallLogTimelineId) {
|
|
1154
|
+
var _a;
|
|
1155
|
+
const host = await DatabaseConfig.getHost();
|
|
1156
|
+
const httpProtocol = await DatabaseConfig.getHttpProtocol();
|
|
1157
|
+
const acknowledgeShortLink = await ShortLinkService.saveShortLinkFor(new URL(httpProtocol, host, new Route(AppApiRoute.toString())
|
|
1158
|
+
.addRoute(new UserOnCallLogTimeline().crudApiPath)
|
|
1159
|
+
.addRoute("/acknowledge-page/" + userOnCallLogTimelineId.toString())));
|
|
1160
|
+
const acknowledgeUrl = await ShortLinkService.getShortenedUrl(acknowledgeShortLink);
|
|
1161
|
+
const episodeLinkOnDashboard = alertEpisode.projectId && alertEpisode.id
|
|
1162
|
+
? (await AlertEpisodeService.getEpisodeLinkInDashboard(alertEpisode.projectId, alertEpisode.id)).toString()
|
|
1163
|
+
: acknowledgeUrl.toString();
|
|
1164
|
+
const templateKey = WhatsAppTemplateIds.AlertEpisodeCreated;
|
|
1165
|
+
const templateVariables = {
|
|
1166
|
+
project_name: ((_a = alertEpisode.project) === null || _a === void 0 ? void 0 : _a.name) || "OneUptime",
|
|
1167
|
+
episode_title: alertEpisode.title || "",
|
|
1168
|
+
acknowledge_url: acknowledgeUrl.toString(),
|
|
1169
|
+
episode_number: alertEpisode.episodeNumber !== undefined
|
|
1170
|
+
? alertEpisode.episodeNumber.toString()
|
|
1171
|
+
: "",
|
|
1172
|
+
episode_link: episodeLinkOnDashboard,
|
|
1173
|
+
};
|
|
1174
|
+
const body = renderWhatsAppTemplate(templateKey, templateVariables);
|
|
1175
|
+
return {
|
|
1176
|
+
to,
|
|
1177
|
+
body,
|
|
1178
|
+
templateKey,
|
|
1179
|
+
templateVariables,
|
|
1180
|
+
templateLanguageCode: WhatsAppTemplateLanguage[templateKey],
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
865
1183
|
async generateEmailTemplateForAlertCreated(to, alert, userOnCallLogTimelineId) {
|
|
866
1184
|
const host = await DatabaseConfig.getHost();
|
|
867
1185
|
const httpProtocol = await DatabaseConfig.getHttpProtocol();
|
|
1186
|
+
const alertNumber = alert.alertNumber
|
|
1187
|
+
? `#${alert.alertNumber}`
|
|
1188
|
+
: "";
|
|
868
1189
|
const vars = {
|
|
869
1190
|
alertTitle: alert.title,
|
|
1191
|
+
alertNumber: alertNumber,
|
|
870
1192
|
projectName: alert.project.name,
|
|
871
1193
|
currentState: alert.currentAlertState.name,
|
|
872
1194
|
alertDescription: await Markdown.convertToHTML(alert.description || "", MarkdownContentType.Email),
|
|
@@ -880,15 +1202,19 @@ export class Service extends DatabaseService {
|
|
|
880
1202
|
toEmail: to,
|
|
881
1203
|
templateType: EmailTemplateType.AcknowledgeAlert,
|
|
882
1204
|
vars: vars,
|
|
883
|
-
subject:
|
|
1205
|
+
subject: `ACTION REQUIRED: Alert ${alertNumber} created - ${alert.title}`,
|
|
884
1206
|
};
|
|
885
1207
|
return emailMessage;
|
|
886
1208
|
}
|
|
887
1209
|
async generateEmailTemplateForIncidentCreated(to, incident, userOnCallLogTimelineId) {
|
|
888
1210
|
const host = await DatabaseConfig.getHost();
|
|
889
1211
|
const httpProtocol = await DatabaseConfig.getHttpProtocol();
|
|
1212
|
+
const incidentNumber = incident.incidentNumber
|
|
1213
|
+
? `#${incident.incidentNumber}`
|
|
1214
|
+
: "";
|
|
890
1215
|
const vars = {
|
|
891
1216
|
incidentTitle: incident.title,
|
|
1217
|
+
incidentNumber: incidentNumber,
|
|
892
1218
|
projectName: incident.project.name,
|
|
893
1219
|
currentState: incident.currentIncidentState.name,
|
|
894
1220
|
incidentDescription: await Markdown.convertToHTML(incident.description || "", MarkdownContentType.Email),
|
|
@@ -903,7 +1229,133 @@ export class Service extends DatabaseService {
|
|
|
903
1229
|
toEmail: to,
|
|
904
1230
|
templateType: EmailTemplateType.AcknowledgeIncident,
|
|
905
1231
|
vars: vars,
|
|
906
|
-
subject:
|
|
1232
|
+
subject: `ACTION REQUIRED: Incident ${incidentNumber} created - ${incident.title}`,
|
|
1233
|
+
};
|
|
1234
|
+
return emailMessage;
|
|
1235
|
+
}
|
|
1236
|
+
async generateEmailTemplateForAlertEpisodeCreated(to, alertEpisode, userOnCallLogTimelineId) {
|
|
1237
|
+
var _a, _b;
|
|
1238
|
+
const host = await DatabaseConfig.getHost();
|
|
1239
|
+
const httpProtocol = await DatabaseConfig.getHttpProtocol();
|
|
1240
|
+
// Fetch alerts that are members of this episode
|
|
1241
|
+
const episodeMembers = await AlertEpisodeMemberService.findBy({
|
|
1242
|
+
query: {
|
|
1243
|
+
alertEpisodeId: alertEpisode.id,
|
|
1244
|
+
},
|
|
1245
|
+
select: {
|
|
1246
|
+
alertId: true,
|
|
1247
|
+
},
|
|
1248
|
+
props: {
|
|
1249
|
+
isRoot: true,
|
|
1250
|
+
},
|
|
1251
|
+
limit: LIMIT_PER_PROJECT,
|
|
1252
|
+
skip: 0,
|
|
1253
|
+
});
|
|
1254
|
+
// Get the alert IDs
|
|
1255
|
+
const alertIds = episodeMembers
|
|
1256
|
+
.map((member) => {
|
|
1257
|
+
return member.alertId;
|
|
1258
|
+
})
|
|
1259
|
+
.filter((id) => {
|
|
1260
|
+
return id !== undefined;
|
|
1261
|
+
});
|
|
1262
|
+
// Fetch full alert data with monitors
|
|
1263
|
+
const alerts = alertIds.length > 0
|
|
1264
|
+
? await AlertService.findBy({
|
|
1265
|
+
query: {
|
|
1266
|
+
_id: QueryHelper.any(alertIds),
|
|
1267
|
+
},
|
|
1268
|
+
select: {
|
|
1269
|
+
_id: true,
|
|
1270
|
+
title: true,
|
|
1271
|
+
alertNumber: true,
|
|
1272
|
+
monitor: {
|
|
1273
|
+
_id: true,
|
|
1274
|
+
name: true,
|
|
1275
|
+
},
|
|
1276
|
+
},
|
|
1277
|
+
props: {
|
|
1278
|
+
isRoot: true,
|
|
1279
|
+
},
|
|
1280
|
+
limit: LIMIT_PER_PROJECT,
|
|
1281
|
+
skip: 0,
|
|
1282
|
+
})
|
|
1283
|
+
: [];
|
|
1284
|
+
// Get unique monitors (resources affected)
|
|
1285
|
+
const monitorNames = new Set();
|
|
1286
|
+
for (const alert of alerts) {
|
|
1287
|
+
if ((_a = alert.monitor) === null || _a === void 0 ? void 0 : _a.name) {
|
|
1288
|
+
monitorNames.add(alert.monitor.name);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
const resourcesAffected = monitorNames.size > 0
|
|
1292
|
+
? Array.from(monitorNames).join(", ")
|
|
1293
|
+
: "No resources identified";
|
|
1294
|
+
// Build alerts list HTML with proper email styling
|
|
1295
|
+
let alertsListHtml = "";
|
|
1296
|
+
if (alerts.length > 0) {
|
|
1297
|
+
const alertRows = [];
|
|
1298
|
+
for (const alert of alerts) {
|
|
1299
|
+
const alertTitle = alert.title || "Untitled Alert";
|
|
1300
|
+
const alertNumber = alert.alertNumber
|
|
1301
|
+
? `#${alert.alertNumber}`
|
|
1302
|
+
: "";
|
|
1303
|
+
const alertLink = (await AlertService.getAlertLinkInDashboard(alertEpisode.projectId, alert.id)).toString();
|
|
1304
|
+
const monitorName = ((_b = alert.monitor) === null || _b === void 0 ? void 0 : _b.name) || "";
|
|
1305
|
+
alertRows.push(`
|
|
1306
|
+
<tr>
|
|
1307
|
+
<td style="padding: 12px 16px; border-bottom: 1px solid #e2e8f0;">
|
|
1308
|
+
<table cellpadding="0" cellspacing="0" width="100%">
|
|
1309
|
+
<tr>
|
|
1310
|
+
<td style="vertical-align: middle;">
|
|
1311
|
+
<span style="display: inline-block; background-color: #dbeafe; color: #1e40af; font-size: 12px; font-weight: 600; padding: 2px 8px; border-radius: 4px; margin-right: 8px;">${alertNumber}</span>
|
|
1312
|
+
<a href="${alertLink}" style="color: #2563eb; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: 500; text-decoration: none;">${alertTitle}</a>
|
|
1313
|
+
${monitorName ? `<span style="display: block; color: #64748b; font-size: 12px; margin-top: 4px;">Monitor: ${monitorName}</span>` : ""}
|
|
1314
|
+
</td>
|
|
1315
|
+
<td style="text-align: right; vertical-align: middle;">
|
|
1316
|
+
<a href="${alertLink}" style="color: #2563eb; font-size: 12px; text-decoration: none;">View →</a>
|
|
1317
|
+
</td>
|
|
1318
|
+
</tr>
|
|
1319
|
+
</table>
|
|
1320
|
+
</td>
|
|
1321
|
+
</tr>
|
|
1322
|
+
`);
|
|
1323
|
+
}
|
|
1324
|
+
if (alertRows.length > 0) {
|
|
1325
|
+
alertsListHtml = `
|
|
1326
|
+
<table cellpadding="0" cellspacing="0" width="100%" style="background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); border-radius: 8px; border: 1px solid #e2e8f0; margin: 8px 0 16px 0;">
|
|
1327
|
+
<tbody>
|
|
1328
|
+
${alertRows.join("")}
|
|
1329
|
+
</tbody>
|
|
1330
|
+
</table>
|
|
1331
|
+
`;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
const episodeNumber = alertEpisode.episodeNumber
|
|
1335
|
+
? `#${alertEpisode.episodeNumber}`
|
|
1336
|
+
: "";
|
|
1337
|
+
const vars = {
|
|
1338
|
+
alertEpisodeTitle: alertEpisode.title,
|
|
1339
|
+
episodeNumber: episodeNumber,
|
|
1340
|
+
projectName: alertEpisode.project.name,
|
|
1341
|
+
currentState: alertEpisode.currentAlertState.name,
|
|
1342
|
+
alertEpisodeDescription: await Markdown.convertToHTML(alertEpisode.description || "", MarkdownContentType.Email),
|
|
1343
|
+
alertEpisodeSeverity: alertEpisode.alertSeverity.name,
|
|
1344
|
+
resourcesAffected: resourcesAffected,
|
|
1345
|
+
rootCause: alertEpisode.rootCause ||
|
|
1346
|
+
"No root cause identified for this alert episode",
|
|
1347
|
+
alertsList: alertsListHtml,
|
|
1348
|
+
alertsCount: alerts.length.toString(),
|
|
1349
|
+
alertEpisodeViewLink: (await AlertEpisodeService.getEpisodeLinkInDashboard(alertEpisode.projectId, alertEpisode.id)).toString(),
|
|
1350
|
+
acknowledgeAlertEpisodeLink: new URL(httpProtocol, host, new Route(AppApiRoute.toString())
|
|
1351
|
+
.addRoute(new UserOnCallLogTimeline().crudApiPath)
|
|
1352
|
+
.addRoute("/acknowledge-page/" + userOnCallLogTimelineId.toString())).toString(),
|
|
1353
|
+
};
|
|
1354
|
+
const emailMessage = {
|
|
1355
|
+
toEmail: to,
|
|
1356
|
+
templateType: EmailTemplateType.AcknowledgeAlertEpisode,
|
|
1357
|
+
vars: vars,
|
|
1358
|
+
subject: `ACTION REQUIRED: Alert Episode ${episodeNumber} created - ${alertEpisode.title}`,
|
|
907
1359
|
};
|
|
908
1360
|
return emailMessage;
|
|
909
1361
|
}
|
|
@@ -918,6 +1370,10 @@ export class Service extends DatabaseService {
|
|
|
918
1370
|
if (options.triggeredByAlertId) {
|
|
919
1371
|
userOnCallLog.triggeredByAlertId = options.triggeredByAlertId;
|
|
920
1372
|
}
|
|
1373
|
+
if (options.triggeredByAlertEpisodeId) {
|
|
1374
|
+
userOnCallLog.triggeredByAlertEpisodeId =
|
|
1375
|
+
options.triggeredByAlertEpisodeId;
|
|
1376
|
+
}
|
|
921
1377
|
userOnCallLog.userNotificationEventType = options.userNotificationEventType;
|
|
922
1378
|
if (options.onCallPolicyExecutionLogId) {
|
|
923
1379
|
userOnCallLog.onCallDutyPolicyExecutionLogId =
|
|
@@ -1043,7 +1499,7 @@ export class Service extends DatabaseService {
|
|
|
1043
1499
|
userId,
|
|
1044
1500
|
userEmailId: userEmail.id,
|
|
1045
1501
|
incidentSeverityId: incidentSeverity.id,
|
|
1046
|
-
ruleType: NotificationRuleType.
|
|
1502
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
1047
1503
|
},
|
|
1048
1504
|
props: {
|
|
1049
1505
|
isRoot: true,
|
|
@@ -1058,7 +1514,8 @@ export class Service extends DatabaseService {
|
|
|
1058
1514
|
notificationRule.userEmailId = userEmail.id;
|
|
1059
1515
|
notificationRule.incidentSeverityId = incidentSeverity.id;
|
|
1060
1516
|
notificationRule.notifyAfterMinutes = 0;
|
|
1061
|
-
notificationRule.ruleType =
|
|
1517
|
+
notificationRule.ruleType =
|
|
1518
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT;
|
|
1062
1519
|
await this.create({
|
|
1063
1520
|
data: notificationRule,
|
|
1064
1521
|
props: {
|
|
@@ -1091,7 +1548,7 @@ export class Service extends DatabaseService {
|
|
|
1091
1548
|
userId,
|
|
1092
1549
|
userEmailId: userEmail.id,
|
|
1093
1550
|
alertSeverityId: alertSeverity.id,
|
|
1094
|
-
ruleType: NotificationRuleType.
|
|
1551
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_ALERT,
|
|
1095
1552
|
},
|
|
1096
1553
|
props: {
|
|
1097
1554
|
isRoot: true,
|
|
@@ -1106,7 +1563,7 @@ export class Service extends DatabaseService {
|
|
|
1106
1563
|
notificationRule.userEmailId = userEmail.id;
|
|
1107
1564
|
notificationRule.alertSeverityId = alertSeverity.id;
|
|
1108
1565
|
notificationRule.notifyAfterMinutes = 0;
|
|
1109
|
-
notificationRule.ruleType = NotificationRuleType.
|
|
1566
|
+
notificationRule.ruleType = NotificationRuleType.ON_CALL_EXECUTED_ALERT;
|
|
1110
1567
|
await this.create({
|
|
1111
1568
|
data: notificationRule,
|
|
1112
1569
|
props: {
|
|
@@ -1229,6 +1686,14 @@ __decorate([
|
|
|
1229
1686
|
ObjectID]),
|
|
1230
1687
|
__metadata("design:returntype", Promise)
|
|
1231
1688
|
], Service.prototype, "generateCallTemplateForIncidentCreated", null);
|
|
1689
|
+
__decorate([
|
|
1690
|
+
CaptureSpan(),
|
|
1691
|
+
__metadata("design:type", Function),
|
|
1692
|
+
__metadata("design:paramtypes", [Phone,
|
|
1693
|
+
AlertEpisode,
|
|
1694
|
+
ObjectID]),
|
|
1695
|
+
__metadata("design:returntype", Promise)
|
|
1696
|
+
], Service.prototype, "generateCallTemplateForAlertEpisodeCreated", null);
|
|
1232
1697
|
__decorate([
|
|
1233
1698
|
CaptureSpan(),
|
|
1234
1699
|
__metadata("design:type", Function),
|
|
@@ -1245,6 +1710,14 @@ __decorate([
|
|
|
1245
1710
|
ObjectID]),
|
|
1246
1711
|
__metadata("design:returntype", Promise)
|
|
1247
1712
|
], Service.prototype, "generateSmsTemplateForIncidentCreated", null);
|
|
1713
|
+
__decorate([
|
|
1714
|
+
CaptureSpan(),
|
|
1715
|
+
__metadata("design:type", Function),
|
|
1716
|
+
__metadata("design:paramtypes", [Phone,
|
|
1717
|
+
AlertEpisode,
|
|
1718
|
+
ObjectID]),
|
|
1719
|
+
__metadata("design:returntype", Promise)
|
|
1720
|
+
], Service.prototype, "generateSmsTemplateForAlertEpisodeCreated", null);
|
|
1248
1721
|
__decorate([
|
|
1249
1722
|
CaptureSpan(),
|
|
1250
1723
|
__metadata("design:type", Function),
|
|
@@ -1261,6 +1734,14 @@ __decorate([
|
|
|
1261
1734
|
ObjectID]),
|
|
1262
1735
|
__metadata("design:returntype", Promise)
|
|
1263
1736
|
], Service.prototype, "generateWhatsAppTemplateForIncidentCreated", null);
|
|
1737
|
+
__decorate([
|
|
1738
|
+
CaptureSpan(),
|
|
1739
|
+
__metadata("design:type", Function),
|
|
1740
|
+
__metadata("design:paramtypes", [Phone,
|
|
1741
|
+
AlertEpisode,
|
|
1742
|
+
ObjectID]),
|
|
1743
|
+
__metadata("design:returntype", Promise)
|
|
1744
|
+
], Service.prototype, "generateWhatsAppTemplateForAlertEpisodeCreated", null);
|
|
1264
1745
|
__decorate([
|
|
1265
1746
|
CaptureSpan(),
|
|
1266
1747
|
__metadata("design:type", Function),
|
|
@@ -1277,6 +1758,14 @@ __decorate([
|
|
|
1277
1758
|
ObjectID]),
|
|
1278
1759
|
__metadata("design:returntype", Promise)
|
|
1279
1760
|
], Service.prototype, "generateEmailTemplateForIncidentCreated", null);
|
|
1761
|
+
__decorate([
|
|
1762
|
+
CaptureSpan(),
|
|
1763
|
+
__metadata("design:type", Function),
|
|
1764
|
+
__metadata("design:paramtypes", [Email,
|
|
1765
|
+
AlertEpisode,
|
|
1766
|
+
ObjectID]),
|
|
1767
|
+
__metadata("design:returntype", Promise)
|
|
1768
|
+
], Service.prototype, "generateEmailTemplateForAlertEpisodeCreated", null);
|
|
1280
1769
|
__decorate([
|
|
1281
1770
|
CaptureSpan(),
|
|
1282
1771
|
__metadata("design:type", Function),
|