diff --git a/packages/server/src/utils/notifications/build-success.ts b/packages/server/src/utils/notifications/build-success.ts index fb8b89f76..8c84d2e67 100644 --- a/packages/server/src/utils/notifications/build-success.ts +++ b/packages/server/src/utils/notifications/build-success.ts @@ -6,209 +6,231 @@ import { renderAsync } from "@react-email/components"; import { format } from "date-fns"; import { and, eq } from "drizzle-orm"; import { - sendDiscordNotification, - sendEmailNotification, - sendGotifyNotification, - sendNtfyNotification, - sendSlackNotification, - sendTelegramNotification, + sendCustomNotification, + sendDiscordNotification, + sendEmailNotification, + sendGotifyNotification, + sendNtfyNotification, + sendSlackNotification, + sendTelegramNotification, } from "./utils"; interface Props { - projectName: string; - applicationName: string; - applicationType: string; - buildLink: string; - organizationId: string; - domains: Domain[]; + projectName: string; + applicationName: string; + applicationType: string; + buildLink: string; + organizationId: string; + domains: Domain[]; } export const sendBuildSuccessNotifications = async ({ - projectName, - applicationName, - applicationType, - buildLink, - organizationId, - domains, + projectName, + applicationName, + applicationType, + buildLink, + organizationId, + domains, }: Props) => { - const date = new Date(); - const unixDate = ~~(Number(date) / 1000); - const notificationList = await db.query.notifications.findMany({ - where: and( - eq(notifications.appDeploy, true), - eq(notifications.organizationId, organizationId), - ), - with: { - email: true, - discord: true, - telegram: true, - slack: true, - gotify: true, - ntfy: true, - }, - }); + const date = new Date(); + const unixDate = ~~(Number(date) / 1000); + const notificationList = await db.query.notifications.findMany({ + where: and( + eq(notifications.appDeploy, true), + eq(notifications.organizationId, organizationId) + ), + with: { + email: true, + discord: true, + telegram: true, + slack: true, + gotify: true, + ntfy: true, + custom: true, + }, + }); - for (const notification of notificationList) { - const { email, discord, telegram, slack, gotify, ntfy } = notification; + for (const notification of notificationList) { + const { email, discord, telegram, slack, gotify, ntfy, custom } = + notification; - if (email) { - const template = await renderAsync( - BuildSuccessEmail({ - projectName, - applicationName, - applicationType, - buildLink, - date: date.toLocaleString(), - }), - ).catch(); - await sendEmailNotification(email, "Build success for dokploy", template); - } + if (email) { + const template = await renderAsync( + BuildSuccessEmail({ + projectName, + applicationName, + applicationType, + buildLink, + date: date.toLocaleString(), + }) + ).catch(); + await sendEmailNotification(email, "Build success for dokploy", template); + } - if (discord) { - const decorate = (decoration: string, text: string) => - `${discord.decoration ? decoration : ""} ${text}`.trim(); + if (discord) { + const decorate = (decoration: string, text: string) => + `${discord.decoration ? decoration : ""} ${text}`.trim(); - await sendDiscordNotification(discord, { - title: decorate(">", "`✅` Build Success"), - color: 0x57f287, - fields: [ - { - name: decorate("`🛠️`", "Project"), - value: projectName, - inline: true, - }, - { - name: decorate("`⚙️`", "Application"), - value: applicationName, - inline: true, - }, - { - name: decorate("`❔`", "Type"), - value: applicationType, - inline: true, - }, - { - name: decorate("`📅`", "Date"), - value: ``, - inline: true, - }, - { - name: decorate("`⌚`", "Time"), - value: ``, - inline: true, - }, - { - name: decorate("`❓`", "Type"), - value: "Successful", - inline: true, - }, - { - name: decorate("`🧷`", "Build Link"), - value: `[Click here to access build link](${buildLink})`, - }, - ], - timestamp: date.toISOString(), - footer: { - text: "Dokploy Build Notification", - }, - }); - } + await sendDiscordNotification(discord, { + title: decorate(">", "`✅` Build Success"), + color: 0x57f287, + fields: [ + { + name: decorate("`🛠️`", "Project"), + value: projectName, + inline: true, + }, + { + name: decorate("`⚙️`", "Application"), + value: applicationName, + inline: true, + }, + { + name: decorate("`❔`", "Type"), + value: applicationType, + inline: true, + }, + { + name: decorate("`📅`", "Date"), + value: ``, + inline: true, + }, + { + name: decorate("`⌚`", "Time"), + value: ``, + inline: true, + }, + { + name: decorate("`❓`", "Type"), + value: "Successful", + inline: true, + }, + { + name: decorate("`🧷`", "Build Link"), + value: `[Click here to access build link](${buildLink})`, + }, + ], + timestamp: date.toISOString(), + footer: { + text: "Dokploy Build Notification", + }, + }); + } - if (gotify) { - const decorate = (decoration: string, text: string) => - `${gotify.decoration ? decoration : ""} ${text}\n`; - await sendGotifyNotification( - gotify, - decorate("✅", "Build Success"), - `${decorate("🛠️", `Project: ${projectName}`)}` + - `${decorate("⚙️", `Application: ${applicationName}`)}` + - `${decorate("❔", `Type: ${applicationType}`)}` + - `${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + - `${decorate("🔗", `Build details:\n${buildLink}`)}`, - ); - } + if (gotify) { + const decorate = (decoration: string, text: string) => + `${gotify.decoration ? decoration : ""} ${text}\n`; + await sendGotifyNotification( + gotify, + decorate("✅", "Build Success"), + `${decorate("🛠️", `Project: ${projectName}`)}` + + `${decorate("⚙️", `Application: ${applicationName}`)}` + + `${decorate("❔", `Type: ${applicationType}`)}` + + `${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + + `${decorate("🔗", `Build details:\n${buildLink}`)}` + ); + } - if (ntfy) { - await sendNtfyNotification( - ntfy, - "Build Success", - "white_check_mark", - `view, Build details, ${buildLink}, clear=true;`, - `🛠Project: ${projectName}\n` + - `⚙️Application: ${applicationName}\n` + - `❔Type: ${applicationType}\n` + - `🕒Date: ${date.toLocaleString()}`, - ); - } + if (ntfy) { + await sendNtfyNotification( + ntfy, + "Build Success", + "white_check_mark", + `view, Build details, ${buildLink}, clear=true;`, + `🛠Project: ${projectName}\n` + + `⚙️Application: ${applicationName}\n` + + `❔Type: ${applicationType}\n` + + `🕒Date: ${date.toLocaleString()}` + ); + } - if (telegram) { - const chunkArray = (array: T[], chunkSize: number): T[][] => - Array.from({ length: Math.ceil(array.length / chunkSize) }, (_, i) => - array.slice(i * chunkSize, i * chunkSize + chunkSize), - ); + if (telegram) { + const chunkArray = (array: T[], chunkSize: number): T[][] => + Array.from({ length: Math.ceil(array.length / chunkSize) }, (_, i) => + array.slice(i * chunkSize, i * chunkSize + chunkSize) + ); - const inlineButton = [ - [ - { - text: "Deployment Logs", - url: buildLink, - }, - ], - ...chunkArray(domains, 2).map((chunk) => - chunk.map((data) => ({ - text: data.host, - url: `${data.https ? "https" : "http"}://${data.host}`, - })), - ), - ]; + const inlineButton = [ + [ + { + text: "Deployment Logs", + url: buildLink, + }, + ], + ...chunkArray(domains, 2).map((chunk) => + chunk.map((data) => ({ + text: data.host, + url: `${data.https ? "https" : "http"}://${data.host}`, + })) + ), + ]; - await sendTelegramNotification( - telegram, - `✅ Build Success\n\nProject: ${projectName}\nApplication: ${applicationName}\nType: ${applicationType}\nDate: ${format(date, "PP")}\nTime: ${format(date, "pp")}`, - inlineButton, - ); - } + await sendTelegramNotification( + telegram, + `✅ Build Success\n\nProject: ${projectName}\nApplication: ${applicationName}\nType: ${applicationType}\nDate: ${format( + date, + "PP" + )}\nTime: ${format(date, "pp")}`, + inlineButton + ); + } - if (slack) { - const { channel } = slack; - await sendSlackNotification(slack, { - channel: channel, - attachments: [ - { - color: "#00FF00", - pretext: ":white_check_mark: *Build Success*", - fields: [ - { - title: "Project", - value: projectName, - short: true, - }, - { - title: "Application", - value: applicationName, - short: true, - }, - { - title: "Type", - value: applicationType, - short: true, - }, - { - title: "Time", - value: date.toLocaleString(), - short: true, - }, - ], - actions: [ - { - type: "button", - text: "View Build Details", - url: buildLink, - }, - ], - }, - ], - }); - } - } + if (slack) { + const { channel } = slack; + await sendSlackNotification(slack, { + channel: channel, + attachments: [ + { + color: "#00FF00", + pretext: ":white_check_mark: *Build Success*", + fields: [ + { + title: "Project", + value: projectName, + short: true, + }, + { + title: "Application", + value: applicationName, + short: true, + }, + { + title: "Type", + value: applicationType, + short: true, + }, + { + title: "Time", + value: date.toLocaleString(), + short: true, + }, + ], + actions: [ + { + type: "button", + text: "View Build Details", + url: buildLink, + }, + ], + }, + ], + }); + } + + if (custom) { + await sendCustomNotification(custom, { + title: "Build Success", + message: "Build completed successfully", + projectName, + applicationName, + applicationType, + buildLink, + timestamp: date.toISOString(), + date: date.toLocaleString(), + domains: domains.map((domain) => domain.host).join(", "), + status: "success", + type: "build", + }); + } + } };