diff --git a/Common/Server/Services/IncidentService.ts b/Common/Server/Services/IncidentService.ts index f97492c661..775b8caca6 100644 --- a/Common/Server/Services/IncidentService.ts +++ b/Common/Server/Services/IncidentService.ts @@ -54,24 +54,12 @@ import Label from "../../Models/DatabaseModels/Label"; import LabelService from "./LabelService"; import IncidentSeverity from "../../Models/DatabaseModels/IncidentSeverity"; import IncidentSeverityService from "./IncidentSeverityService"; -import { - WorkspaceMessageBlock, - WorkspaceMessagePayloadButton, - WorkspacePayloadButtons, - WorkspacePayloadDivider, - WorkspacePayloadHeader, - WorkspacePayloadMarkdown, -} from "../../Types/Workspace/WorkspaceMessagePayload"; -import WorkspaceNotificationRuleService, { - MessageBlocksByWorkspaceType, -} from "./WorkspaceNotificationRuleService"; -import NotificationRuleEventType from "../../Types/Workspace/NotificationRules/EventType"; + import { WorkspaceChannel, WorkspaceSendMessageResponse, } from "../Utils/Workspace/WorkspaceBase"; -import WorkspaceType from "../../Types/Workspace/WorkspaceType"; -import SlackActionType from "../Utils/Workspace/Slack/Actions/ActionTypes"; +import IncidentWorkspaceMessages from "../Utils/Workspace/WorkspaceMessages/Incident"; export class Service extends DatabaseService { public constructor() { @@ -545,7 +533,7 @@ ${createdItem.remediationNotes || "No remediation notes provided."}`, const workspaceResult: { channelsCreated: Array; workspaceSendMessageResponse: WorkspaceSendMessageResponse; - } | null = await this.notifyWorkspaceOnIncidentCreate({ + } | null = await IncidentWorkspaceMessages.notifyWorkspaceOnIncidentCreate({ projectId: createdItem.projectId, incidentId: createdItem.id!, incidentNumber: createdItem.incidentNumber!, @@ -1416,259 +1404,5 @@ ${incidentSeverity.name} logger.error(err); }); } - - public async notifyWorkspaceOnIncidentCreate(data: { - projectId: ObjectID; - incidentId: ObjectID; - incidentNumber: number; - }): Promise<{ - channelsCreated: WorkspaceChannel[]; - workspaceSendMessageResponse: WorkspaceSendMessageResponse; - } | null> { - try { - // we will notify the workspace about the incident creation with the bot tokken which is in WorkspaceProjectAuth Table. - return await WorkspaceNotificationRuleService.createInviteAndPostToChannelsBasedOnRules( - { - projectId: data.projectId, - notificationFor: { - incidentId: data.incidentId, - }, - notificationRuleEventType: NotificationRuleEventType.Incident, - channelNameSiffix: data.incidentNumber.toString(), - messageBlocksByWorkspaceType: - await this.getWorkspaceMessageBlocksForIncidentCreate({ - incidentId: data.incidentId, - }), - }, - ); - } catch (err) { - // log the error and continue. - logger.error(err); - return null; - } - } - - public async getWorkspaceMessageBlocksForIncidentCreate(data: { - incidentId: ObjectID; - }): Promise> { - const messageBlocks: Array = []; - - // slack and teams workspasce types. - - const incident: Model | null = await this.findOneById({ - id: data.incidentId, - select: { - projectId: true, - incidentNumber: true, - title: true, - description: true, - incidentSeverity: { - name: true, - }, - rootCause: true, - remediationNotes: true, - currentIncidentState: { - name: true, - }, - monitors: { - name: true, - _id: true, - }, - }, - props: { - isRoot: true, - }, - }); - - if (!incident) { - throw new BadDataException("Incident not found"); - } - - // Slack. - - const blockSlack: Array = []; - - if (incident.incidentNumber) { - const markdownBlock1: WorkspacePayloadHeader = { - _type: "WorkspacePayloadHeader", - text: `:rotating_light: **Incident #${incident.incidentNumber}**`, - }; - blockSlack.push(markdownBlock1); - } - - if (incident.title) { - const markdownBlock2: WorkspacePayloadMarkdown = { - _type: "WorkspacePayloadMarkdown", - text: `**[${incident.title}](${(await this.getIncidentLinkInDashboard(incident.projectId!, incident.id!)).toString()})**`, - }; - blockSlack.push(markdownBlock2); - } - - if (incident.description) { - const markdownBlock3: WorkspacePayloadMarkdown = { - _type: "WorkspacePayloadMarkdown", - text: `${incident.description}`, - }; - blockSlack.push(markdownBlock3); - } - - if (incident.currentIncidentState?.name) { - const markdownBlock7: WorkspacePayloadMarkdown = { - _type: "WorkspacePayloadMarkdown", - text: `:arrow_right: **Incident State**: ${incident.currentIncidentState.name}`, - }; - blockSlack.push(markdownBlock7); - } - - if (incident.incidentSeverity?.name) { - const markdownBlock4: WorkspacePayloadMarkdown = { - _type: "WorkspacePayloadMarkdown", - text: `:warning: **Severity**: ${incident.incidentSeverity.name}`, - }; - blockSlack.push(markdownBlock4); - } - - // check for monitors. - if (incident.monitors && incident.monitors.length > 0) { - let text: string = `:earth_americas: *Resources Affected*:\n`; - - for (const monitor of incident.monitors) { - text += `- [${monitor.name}](${(await MonitorService.getMonitorLinkInDashboard(incident.projectId!, monitor.id!)).toString()})\n`; - } - - // now add text to markdwon block. - const markdownBlock5: WorkspacePayloadMarkdown = { - _type: "WorkspacePayloadMarkdown", - text: text, - }; - - blockSlack.push(markdownBlock5); - } - - if (incident.rootCause) { - const markdownBlock5: WorkspacePayloadMarkdown = { - _type: "WorkspacePayloadMarkdown", - text: `:page_facing_up: **Root Cause**: -${incident.rootCause}`, - }; - blockSlack.push(markdownBlock5); - } - - if (incident.remediationNotes) { - const markdownBlock6: WorkspacePayloadMarkdown = { - _type: "WorkspacePayloadMarkdown", - text: `:dart: **Remediation Notes**: -${incident.remediationNotes}`, - }; - blockSlack.push(markdownBlock6); - } - - // add divider. - - const dividerBlock: WorkspacePayloadDivider = { - _type: "WorkspacePayloadDivider", - }; - - blockSlack.push(dividerBlock); - - // now add buttons. - // View Incident. - // Execute On Call - // Acknowledge incident - // Resolve Incident. - // Change Incident State. - // Add Note. - - const buttons: Array = []; - - // view incident. - const viewIncidentButton: WorkspaceMessagePayloadButton = { - _type: "WorkspaceMessagePayloadButton", - title: "View Incident", - url: await this.getIncidentLinkInDashboard( - incident.projectId!, - incident.id!, - ), - value: "view_incident", - actionId: SlackActionType.ViewIncident, - }; - - buttons.push(viewIncidentButton); - - // execute on call. - const executeOnCallButton: WorkspaceMessagePayloadButton = { - _type: "WorkspaceMessagePayloadButton", - title: ":telephone_receiver: Execute On Call", - value: "execute_on_call", - actionId: SlackActionType.ExecuteIncidentOnCallPolicy, - }; - - buttons.push(executeOnCallButton); - - // acknowledge incident. - const acknowledgeIncidentButton: WorkspaceMessagePayloadButton = { - _type: "WorkspaceMessagePayloadButton", - title: ":eyes: Acknowledge Incident", - value: "acknowledge_incident", - actionId: SlackActionType.AcknowledgeIncident, - }; - - buttons.push(acknowledgeIncidentButton); - - // resolve incident. - const resolveIncidentButton: WorkspaceMessagePayloadButton = { - _type: "WorkspaceMessagePayloadButton", - title: ":white_check_mark: Resolve Incident", - value: "resolve_incident", - actionId: SlackActionType.ResolveIncident, - }; - - buttons.push(resolveIncidentButton); - - // change incident state. - const changeIncidentStateButton: WorkspaceMessagePayloadButton = { - _type: "WorkspaceMessagePayloadButton", - title: ":arrow_right: Change Incident State", - value: "change_incident_state", - actionId: SlackActionType.ChangeIncidentState, - }; - - buttons.push(changeIncidentStateButton); - - // add note. - const addNoteButton: WorkspaceMessagePayloadButton = { - _type: "WorkspaceMessagePayloadButton", - title: ":page_facing_up: Add Note", - value: "add_note", - actionId: SlackActionType.AddIncidentNote, - }; - - buttons.push(addNoteButton); - - const workspacePayloadButtons: WorkspacePayloadButtons = { - buttons: buttons, - _type: "WorkspacePayloadButtons", - }; - - blockSlack.push(workspacePayloadButtons); - - messageBlocks.push({ - workspaceType: WorkspaceType.Slack, - messageBlocks: blockSlack, - }); - - // teams. - - const blocksTeams: Array = []; - - // TODO: Add teams blocks. - - messageBlocks.push({ - workspaceType: WorkspaceType.MicrosoftTeams, - messageBlocks: blocksTeams, - }); - - return messageBlocks; - } } export default new Service(); diff --git a/Common/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.ts b/Common/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.ts new file mode 100644 index 0000000000..d2cfc25218 --- /dev/null +++ b/Common/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.ts @@ -0,0 +1,195 @@ +import Incident from "../../../../../Models/DatabaseModels/Incident"; +import BadDataException from "../../../../../Types/Exception/BadDataException"; +import { + WorkspaceMessageBlock, + WorkspaceMessagePayloadButton, + WorkspacePayloadButtons, + WorkspacePayloadDivider, + WorkspacePayloadHeader, + WorkspacePayloadMarkdown, +} from "../../../../../Types/Workspace/WorkspaceMessagePayload"; +import IncidentService from "../../../../Services/IncidentService"; +import MonitorService from "../../../../Services/MonitorService"; +import SlackActionType from "../../../../Utils/Workspace/Slack/Actions/ActionTypes"; + +export default class MicrosoftTeamsIncidentMessages { + public static async getIncidentCreateMessageBlocks(data: { + incident: Incident; + }): Promise> { + const incident: Incident = data.incident; + + if (!incident) { + throw new BadDataException("Incident not found"); + } + + // Slack. + + const blockSlack: Array = []; + + if (incident.incidentNumber) { + const markdownBlock1: WorkspacePayloadHeader = { + _type: "WorkspacePayloadHeader", + text: `:rotating_light: **Incident #${incident.incidentNumber}**`, + }; + blockSlack.push(markdownBlock1); + } + + if (incident.title) { + const markdownBlock2: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `**[${incident.title}](${(await IncidentService.getIncidentLinkInDashboard(incident.projectId!, incident.id!)).toString()})**`, + }; + blockSlack.push(markdownBlock2); + } + + if (incident.description) { + const markdownBlock3: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `${incident.description}`, + }; + blockSlack.push(markdownBlock3); + } + + if (incident.currentIncidentState?.name) { + const markdownBlock7: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `:arrow_right: **Incident State**: ${incident.currentIncidentState.name}`, + }; + blockSlack.push(markdownBlock7); + } + + if (incident.incidentSeverity?.name) { + const markdownBlock4: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `:warning: **Severity**: ${incident.incidentSeverity.name}`, + }; + blockSlack.push(markdownBlock4); + } + + // check for monitors. + if (incident.monitors && incident.monitors.length > 0) { + let text: string = `:earth_americas: *Resources Affected*:\n`; + + for (const monitor of incident.monitors) { + text += `- [${monitor.name}](${(await MonitorService.getMonitorLinkInDashboard(incident.projectId!, monitor.id!)).toString()})\n`; + } + + // now add text to markdwon block. + const markdownBlock5: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: text, + }; + + blockSlack.push(markdownBlock5); + } + + if (incident.rootCause) { + const markdownBlock5: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `:page_facing_up: **Root Cause**: + ${incident.rootCause}`, + }; + blockSlack.push(markdownBlock5); + } + + if (incident.remediationNotes) { + const markdownBlock6: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `:dart: **Remediation Notes**: + ${incident.remediationNotes}`, + }; + blockSlack.push(markdownBlock6); + } + + // add divider. + + const dividerBlock: WorkspacePayloadDivider = { + _type: "WorkspacePayloadDivider", + }; + + blockSlack.push(dividerBlock); + + // now add buttons. + // View Incident. + // Execute On Call + // Acknowledge incident + // Resolve Incident. + // Change Incident State. + // Add Note. + + const buttons: Array = []; + + // view incident. + const viewIncidentButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: "View Incident", + url: await IncidentService.getIncidentLinkInDashboard( + incident.projectId!, + incident.id!, + ), + value: "view_incident", + actionId: SlackActionType.ViewIncident, + }; + + buttons.push(viewIncidentButton); + + // execute on call. + const executeOnCallButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":telephone_receiver: Execute On Call", + value: "execute_on_call", + actionId: SlackActionType.ExecuteIncidentOnCallPolicy, + }; + + buttons.push(executeOnCallButton); + + // acknowledge incident. + const acknowledgeIncidentButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":eyes: Acknowledge Incident", + value: "acknowledge_incident", + actionId: SlackActionType.AcknowledgeIncident, + }; + + buttons.push(acknowledgeIncidentButton); + + // resolve incident. + const resolveIncidentButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":white_check_mark: Resolve Incident", + value: "resolve_incident", + actionId: SlackActionType.ResolveIncident, + }; + + buttons.push(resolveIncidentButton); + + // change incident state. + const changeIncidentStateButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":arrow_right: Change Incident State", + value: "change_incident_state", + actionId: SlackActionType.ChangeIncidentState, + }; + + buttons.push(changeIncidentStateButton); + + // add note. + const addNoteButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":page_facing_up: Add Note", + value: "add_note", + actionId: SlackActionType.AddIncidentNote, + }; + + buttons.push(addNoteButton); + + const workspacePayloadButtons: WorkspacePayloadButtons = { + buttons: buttons, + _type: "WorkspacePayloadButtons", + }; + + blockSlack.push(workspacePayloadButtons); + + return blockSlack; + } +} diff --git a/Common/Server/Utils/Workspace/Slack/Messages/Incident.ts b/Common/Server/Utils/Workspace/Slack/Messages/Incident.ts new file mode 100644 index 0000000000..2b892c7353 --- /dev/null +++ b/Common/Server/Utils/Workspace/Slack/Messages/Incident.ts @@ -0,0 +1,195 @@ +import Incident from "../../../../../Models/DatabaseModels/Incident"; +import BadDataException from "../../../../../Types/Exception/BadDataException"; +import { + WorkspaceMessageBlock, + WorkspaceMessagePayloadButton, + WorkspacePayloadButtons, + WorkspacePayloadDivider, + WorkspacePayloadHeader, + WorkspacePayloadMarkdown, +} from "../../../../../Types/Workspace/WorkspaceMessagePayload"; +import IncidentService from "../../../../Services/IncidentService"; +import MonitorService from "../../../../Services/MonitorService"; +import SlackActionType from "../../../../Utils/Workspace/Slack/Actions/ActionTypes"; + +export default class SlackIncidentMessages { + public static async getIncidentCreateMessageBlocks(data: { + incident: Incident; + }): Promise> { + const incident: Incident = data.incident; + + if (!incident) { + throw new BadDataException("Incident not found"); + } + + // Slack. + + const blockSlack: Array = []; + + if (incident.incidentNumber) { + const markdownBlock1: WorkspacePayloadHeader = { + _type: "WorkspacePayloadHeader", + text: `:rotating_light: Incident #${incident.incidentNumber}`, + }; + blockSlack.push(markdownBlock1); + } + + if (incident.title) { + const markdownBlock2: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `**[${incident.title}](${(await IncidentService.getIncidentLinkInDashboard(incident.projectId!, incident.id!)).toString()})**`, + }; + blockSlack.push(markdownBlock2); + } + + if (incident.description) { + const markdownBlock3: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `${incident.description}`, + }; + blockSlack.push(markdownBlock3); + } + + if (incident.currentIncidentState?.name) { + const markdownBlock7: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `:arrow_right: **Incident State**: ${incident.currentIncidentState.name}`, + }; + blockSlack.push(markdownBlock7); + } + + if (incident.incidentSeverity?.name) { + const markdownBlock4: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `:warning: **Severity**: ${incident.incidentSeverity.name}`, + }; + blockSlack.push(markdownBlock4); + } + + // check for monitors. + if (incident.monitors && incident.monitors.length > 0) { + let text: string = `:earth_americas: **Resources Affected**:\n`; + + for (const monitor of incident.monitors) { + text += `- [${monitor.name}](${(await MonitorService.getMonitorLinkInDashboard(incident.projectId!, monitor.id!)).toString()})\n`; + } + + // now add text to markdwon block. + const markdownBlock5: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: text, + }; + + blockSlack.push(markdownBlock5); + } + + if (incident.rootCause) { + const markdownBlock5: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `:page_facing_up: **Root Cause**: + ${incident.rootCause}`, + }; + blockSlack.push(markdownBlock5); + } + + if (incident.remediationNotes) { + const markdownBlock6: WorkspacePayloadMarkdown = { + _type: "WorkspacePayloadMarkdown", + text: `:dart: **Remediation Notes**: + ${incident.remediationNotes}`, + }; + blockSlack.push(markdownBlock6); + } + + // add divider. + + const dividerBlock: WorkspacePayloadDivider = { + _type: "WorkspacePayloadDivider", + }; + + blockSlack.push(dividerBlock); + + // now add buttons. + // View Incident. + // Execute On Call + // Acknowledge incident + // Resolve Incident. + // Change Incident State. + // Add Note. + + const buttons: Array = []; + + // view incident. + const viewIncidentButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: "View Incident", + url: await IncidentService.getIncidentLinkInDashboard( + incident.projectId!, + incident.id!, + ), + value: "view_incident", + actionId: SlackActionType.ViewIncident, + }; + + buttons.push(viewIncidentButton); + + // execute on call. + const executeOnCallButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":telephone_receiver: Execute On Call", + value: "execute_on_call", + actionId: SlackActionType.ExecuteIncidentOnCallPolicy, + }; + + buttons.push(executeOnCallButton); + + // acknowledge incident. + const acknowledgeIncidentButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":eyes: Acknowledge Incident", + value: "acknowledge_incident", + actionId: SlackActionType.AcknowledgeIncident, + }; + + buttons.push(acknowledgeIncidentButton); + + // resolve incident. + const resolveIncidentButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":white_check_mark: Resolve Incident", + value: "resolve_incident", + actionId: SlackActionType.ResolveIncident, + }; + + buttons.push(resolveIncidentButton); + + // change incident state. + const changeIncidentStateButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":arrow_right: Change Incident State", + value: "change_incident_state", + actionId: SlackActionType.ChangeIncidentState, + }; + + buttons.push(changeIncidentStateButton); + + // add note. + const addNoteButton: WorkspaceMessagePayloadButton = { + _type: "WorkspaceMessagePayloadButton", + title: ":page_facing_up: Add Note", + value: "add_note", + actionId: SlackActionType.AddIncidentNote, + }; + + buttons.push(addNoteButton); + + const workspacePayloadButtons: WorkspacePayloadButtons = { + buttons: buttons, + _type: "WorkspacePayloadButtons", + }; + + blockSlack.push(workspacePayloadButtons); + + return blockSlack; + } +} diff --git a/Common/Server/Utils/Workspace/Slack/Slack.ts b/Common/Server/Utils/Workspace/Slack/Slack.ts index 49a58d1838..cae54f89e5 100644 --- a/Common/Server/Utils/Workspace/Slack/Slack.ts +++ b/Common/Server/Utils/Workspace/Slack/Slack.ts @@ -421,6 +421,7 @@ export default class SlackUtil extends WorkspaceBase { { channel: data.workspaceChannel.id, blocks: data.blocks, + unfurl_links: false, }, { Authorization: `Bearer ${data.authToken}`, diff --git a/Common/Server/Utils/Workspace/WorkspaceMessages/Incident.ts b/Common/Server/Utils/Workspace/WorkspaceMessages/Incident.ts new file mode 100644 index 0000000000..9eef798674 --- /dev/null +++ b/Common/Server/Utils/Workspace/WorkspaceMessages/Incident.ts @@ -0,0 +1,106 @@ +import Incident from "../../../../Models/DatabaseModels/Incident"; +import BadDataException from "../../../../Types/Exception/BadDataException"; +import ObjectID from "../../../../Types/ObjectID"; +import NotificationRuleEventType from "../../../../Types/Workspace/NotificationRules/EventType"; +import { WorkspaceMessageBlock } from "../../../../Types/Workspace/WorkspaceMessagePayload"; +import WorkspaceType from "../../../../Types/Workspace/WorkspaceType"; +import IncidentService from "../../../Services/IncidentService"; +import WorkspaceNotificationRuleService, { + MessageBlocksByWorkspaceType, +} from "../../../Services/WorkspaceNotificationRuleService"; +import logger from "../../Logger"; +import SlackIncidentMessages from "../Slack/Messages/Incident"; +import { + WorkspaceChannel, + WorkspaceSendMessageResponse, +} from "../WorkspaceBase"; + +export default class IncidentWorkspaceMessages { + public static async notifyWorkspaceOnIncidentCreate(data: { + projectId: ObjectID; + incidentId: ObjectID; + incidentNumber: number; + }): Promise<{ + channelsCreated: WorkspaceChannel[]; + workspaceSendMessageResponse: WorkspaceSendMessageResponse; + } | null> { + try { + // we will notify the workspace about the incident creation with the bot tokken which is in WorkspaceProjectAuth Table. + return await WorkspaceNotificationRuleService.createInviteAndPostToChannelsBasedOnRules( + { + projectId: data.projectId, + notificationFor: { + incidentId: data.incidentId, + }, + notificationRuleEventType: NotificationRuleEventType.Incident, + channelNameSiffix: data.incidentNumber.toString(), + messageBlocksByWorkspaceType: + await this.getIncidentCreateMessageBlocks({ + incidentId: data.incidentId, + }), + }, + ); + } catch (err) { + // log the error and continue. + logger.error(err); + return null; + } + } + + public static async getIncidentCreateMessageBlocks(data: { + incidentId: ObjectID; + }): Promise> { + const { incidentId } = data; + // slack and teams workspasce types. + + const incident: Incident | null = await IncidentService.findOneById({ + id: incidentId, + select: { + projectId: true, + incidentNumber: true, + title: true, + description: true, + incidentSeverity: { + name: true, + }, + rootCause: true, + remediationNotes: true, + currentIncidentState: { + name: true, + }, + monitors: { + name: true, + _id: true, + }, + }, + props: { + isRoot: true, + }, + }); + + if (!incident) { + throw new BadDataException("Incident not found"); + } + + const slackBlocks: WorkspaceMessageBlock[] = + await SlackIncidentMessages.getIncidentCreateMessageBlocks({ + incident: incident, + }); + + const microsoftTeamsBlocks: WorkspaceMessageBlock[] = + await SlackIncidentMessages.getIncidentCreateMessageBlocks({ + incident: incident, + }); + + return [ + { + workspaceType: WorkspaceType.Slack, + messageBlocks: slackBlocks, + }, + { + workspaceType: WorkspaceType.MicrosoftTeams, + messageBlocks: microsoftTeamsBlocks, + }, + ]; + } +}