refactor: improve error handling in notification components

- Enhanced error messages in HandleNotifications and notificationRouter to provide more specific feedback.
- Updated email and Discord notification functions to throw detailed errors on failure.
- Ensured consistent error handling across notification utilities for better debugging.
This commit is contained in:
Mauricio Siu
2025-11-26 02:39:01 -05:00
parent 55748749fd
commit bacadccaa9
8 changed files with 1061 additions and 1034 deletions
@@ -1261,8 +1261,10 @@ export const HandleNotifications = ({ notificationId }: Props) => {
}); });
} }
toast.success("Connection Success"); toast.success("Connection Success");
} catch { } catch (error) {
toast.error("Error testing the provider"); toast.error(
`Error testing the provider ${error instanceof Error ? error.message : "Unknown error"}`,
);
} }
}} }}
> >
@@ -111,7 +111,7 @@ export const notificationRouter = createTRPCRouter({
} catch (error) { } catch (error) {
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "BAD_REQUEST",
message: "Error testing the notification", message: `${error instanceof Error ? error.message : "Unknown error"}`,
cause: error, cause: error,
}); });
} }
@@ -228,7 +228,7 @@ export const notificationRouter = createTRPCRouter({
} catch (error) { } catch (error) {
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "BAD_REQUEST",
message: "Error testing the notification", message: `${error instanceof Error ? error.message : "Unknown error"}`,
cause: error, cause: error,
}); });
} }
@@ -285,7 +285,7 @@ export const notificationRouter = createTRPCRouter({
} catch (error) { } catch (error) {
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "BAD_REQUEST",
message: "Error testing the notification", message: `${error instanceof Error ? error.message : "Unknown error"}`,
cause: error, cause: error,
}); });
} }
@@ -7,8 +7,8 @@ import { and, eq } from "drizzle-orm";
import { import {
sendDiscordNotification, sendDiscordNotification,
sendEmailNotification, sendEmailNotification,
sendLarkNotification,
sendGotifyNotification, sendGotifyNotification,
sendLarkNotification,
sendNtfyNotification, sendNtfyNotification,
sendSlackNotification, sendSlackNotification,
sendTelegramNotification, sendTelegramNotification,
@@ -52,279 +52,287 @@ export const sendBuildErrorNotifications = async ({
for (const notification of notificationList) { for (const notification of notificationList) {
const { email, discord, telegram, slack, gotify, ntfy, lark } = const { email, discord, telegram, slack, gotify, ntfy, lark } =
notification; notification;
if (email) { try {
const template = await renderAsync( if (email) {
BuildFailedEmail({ const template = await renderAsync(
projectName, BuildFailedEmail({
applicationName, projectName,
applicationType, applicationName,
errorMessage: errorMessage, applicationType,
buildLink, errorMessage: errorMessage,
date: date.toLocaleString(), buildLink,
}), date: date.toLocaleString(),
).catch(); }),
await sendEmailNotification(email, "Build failed for dokploy", template); ).catch();
} await sendEmailNotification(
email,
"Build failed for dokploy",
template,
);
}
if (discord) { if (discord) {
const decorate = (decoration: string, text: string) => const decorate = (decoration: string, text: string) =>
`${discord.decoration ? decoration : ""} ${text}`.trim(); `${discord.decoration ? decoration : ""} ${text}`.trim();
const limitCharacter = 800; const limitCharacter = 800;
const truncatedErrorMessage = errorMessage.substring(0, limitCharacter); const truncatedErrorMessage = errorMessage.substring(0, limitCharacter);
await sendDiscordNotification(discord, { await sendDiscordNotification(discord, {
title: decorate(">", "`⚠️` Build Failed"), title: decorate(">", "`⚠️` Build Failed"),
color: 0xed4245, color: 0xed4245,
fields: [ fields: [
{ {
name: decorate("`🛠️`", "Project"), name: decorate("`🛠️`", "Project"),
value: projectName, value: projectName,
inline: true, inline: true,
},
{
name: decorate("`⚙️`", "Application"),
value: applicationName,
inline: true,
},
{
name: decorate("`❔`", "Type"),
value: applicationType,
inline: true,
},
{
name: decorate("`📅`", "Date"),
value: `<t:${unixDate}:D>`,
inline: true,
},
{
name: decorate("`⌚`", "Time"),
value: `<t:${unixDate}:t>`,
inline: true,
},
{
name: decorate("`❓`", "Type"),
value: "Failed",
inline: true,
},
{
name: decorate("`⚠️`", "Error Message"),
value: `\`\`\`${truncatedErrorMessage}\`\`\``,
},
{
name: decorate("`🧷`", "Build Link"),
value: `[Click here to access build link](${buildLink})`,
},
],
timestamp: date.toISOString(),
footer: {
text: "Dokploy Build Notification",
}, },
{ });
name: decorate("`⚙️`", "Application"), }
value: applicationName,
inline: true,
},
{
name: decorate("`❔`", "Type"),
value: applicationType,
inline: true,
},
{
name: decorate("`📅`", "Date"),
value: `<t:${unixDate}:D>`,
inline: true,
},
{
name: decorate("`⌚`", "Time"),
value: `<t:${unixDate}:t>`,
inline: true,
},
{
name: decorate("`❓`", "Type"),
value: "Failed",
inline: true,
},
{
name: decorate("`⚠️`", "Error Message"),
value: `\`\`\`${truncatedErrorMessage}\`\`\``,
},
{
name: decorate("`🧷`", "Build Link"),
value: `[Click here to access build link](${buildLink})`,
},
],
timestamp: date.toISOString(),
footer: {
text: "Dokploy Build Notification",
},
});
}
if (gotify) { if (gotify) {
const decorate = (decoration: string, text: string) => const decorate = (decoration: string, text: string) =>
`${gotify.decoration ? decoration : ""} ${text}\n`; `${gotify.decoration ? decoration : ""} ${text}\n`;
await sendGotifyNotification( await sendGotifyNotification(
gotify, gotify,
decorate("⚠️", "Build Failed"), decorate("⚠️", "Build Failed"),
`${decorate("🛠️", `Project: ${projectName}`)}` + `${decorate("🛠️", `Project: ${projectName}`)}` +
`${decorate("⚙️", `Application: ${applicationName}`)}` + `${decorate("⚙️", `Application: ${applicationName}`)}` +
`${decorate("❔", `Type: ${applicationType}`)}` + `${decorate("❔", `Type: ${applicationType}`)}` +
`${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + `${decorate("🕒", `Date: ${date.toLocaleString()}`)}` +
`${decorate("⚠️", `Error:\n${errorMessage}`)}` + `${decorate("⚠️", `Error:\n${errorMessage}`)}` +
`${decorate("🔗", `Build details:\n${buildLink}`)}`, `${decorate("🔗", `Build details:\n${buildLink}`)}`,
); );
} }
if (ntfy) { if (ntfy) {
await sendNtfyNotification( await sendNtfyNotification(
ntfy, ntfy,
"Build Failed", "Build Failed",
"warning", "warning",
`view, Build details, ${buildLink}, clear=true;`, `view, Build details, ${buildLink}, clear=true;`,
`🛠️Project: ${projectName}\n` + `🛠️Project: ${projectName}\n` +
`⚙️Application: ${applicationName}\n` + `⚙️Application: ${applicationName}\n` +
`❔Type: ${applicationType}\n` + `❔Type: ${applicationType}\n` +
`🕒Date: ${date.toLocaleString()}\n` + `🕒Date: ${date.toLocaleString()}\n` +
`⚠️Error:\n${errorMessage}`, `⚠️Error:\n${errorMessage}`,
); );
} }
if (telegram) { if (telegram) {
const inlineButton = [ const inlineButton = [
[ [
{ {
text: "Deployment Logs", text: "Deployment Logs",
url: buildLink, url: buildLink,
}, },
], ],
]; ];
await sendTelegramNotification( await sendTelegramNotification(
telegram, telegram,
`<b>⚠️ Build Failed</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Type:</b> ${applicationType}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}\n\n<b>Error:</b>\n<pre>${errorMessage}</pre>`, `<b>⚠️ Build Failed</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Type:</b> ${applicationType}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}\n\n<b>Error:</b>\n<pre>${errorMessage}</pre>`,
inlineButton, inlineButton,
); );
} }
if (slack) { if (slack) {
const { channel } = slack; const { channel } = slack;
await sendSlackNotification(slack, { await sendSlackNotification(slack, {
channel: channel, channel: channel,
attachments: [ attachments: [
{ {
color: "#FF0000", color: "#FF0000",
pretext: ":warning: *Build Failed*", pretext: ":warning: *Build Failed*",
fields: [ fields: [
{ {
title: "Project", title: "Project",
value: projectName, value: projectName,
short: true, short: true,
}, },
{ {
title: "Application", title: "Application",
value: applicationName, value: applicationName,
short: true, short: true,
}, },
{ {
title: "Type", title: "Type",
value: applicationType, value: applicationType,
short: true, short: true,
}, },
{ {
title: "Time", title: "Time",
value: date.toLocaleString(), value: date.toLocaleString(),
short: true, short: true,
}, },
{ {
title: "Error", title: "Error",
value: `\`\`\`${errorMessage}\`\`\``, value: `\`\`\`${errorMessage}\`\`\``,
short: false, short: false,
}, },
], ],
actions: [ actions: [
{ {
type: "button", type: "button",
text: "View Build Details", text: "View Build Details",
url: buildLink, url: buildLink,
}, },
], ],
}, },
], ],
}); });
} }
if (lark) { if (lark) {
const limitCharacter = 800; const limitCharacter = 800;
const truncatedErrorMessage = errorMessage.substring(0, limitCharacter); const truncatedErrorMessage = errorMessage.substring(0, limitCharacter);
await sendLarkNotification(lark, { await sendLarkNotification(lark, {
msg_type: "interactive", msg_type: "interactive",
card: { card: {
schema: "2.0", schema: "2.0",
config: { config: {
update_multi: true, update_multi: true,
style: { style: {
text_size: { text_size: {
normal_v2: { normal_v2: {
default: "normal", default: "normal",
pc: "normal", pc: "normal",
mobile: "heading", mobile: "heading",
},
}, },
}, },
}, },
}, header: {
header: { title: {
title: { tag: "plain_text",
tag: "plain_text", content: "⚠️ Build Failed",
content: "⚠️ Build Failed",
},
subtitle: {
tag: "plain_text",
content: "",
},
template: "red",
padding: "12px 12px 12px 12px",
},
body: {
direction: "vertical",
padding: "12px 12px 12px 12px",
elements: [
{
tag: "column_set",
columns: [
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Project:**\n${projectName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Type:**\n${applicationType}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Error Message:**\n\`\`\`\n${truncatedErrorMessage}\n\`\`\``,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Application:**\n${applicationName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
],
}, },
{ subtitle: {
tag: "button", tag: "plain_text",
text: { content: "",
tag: "plain_text", },
content: "View Build Details", template: "red",
padding: "12px 12px 12px 12px",
},
body: {
direction: "vertical",
padding: "12px 12px 12px 12px",
elements: [
{
tag: "column_set",
columns: [
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Project:**\n${projectName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Type:**\n${applicationType}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Error Message:**\n\`\`\`\n${truncatedErrorMessage}\n\`\`\``,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Application:**\n${applicationName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
],
}, },
type: "danger", {
width: "default", tag: "button",
size: "medium", text: {
behaviors: [ tag: "plain_text",
{ content: "View Build Details",
type: "open_url",
default_url: buildLink,
pc_url: "",
ios_url: "",
android_url: "",
}, },
], type: "danger",
margin: "0px 0px 0px 0px", width: "default",
}, size: "medium",
], behaviors: [
{
type: "open_url",
default_url: buildLink,
pc_url: "",
ios_url: "",
android_url: "",
},
],
margin: "0px 0px 0px 0px",
},
],
},
}, },
}, });
}); }
} catch (error) {
console.log(error);
} }
} }
}; };
@@ -8,8 +8,8 @@ import { and, eq } from "drizzle-orm";
import { import {
sendDiscordNotification, sendDiscordNotification,
sendEmailNotification, sendEmailNotification,
sendLarkNotification,
sendGotifyNotification, sendGotifyNotification,
sendLarkNotification,
sendNtfyNotification, sendNtfyNotification,
sendSlackNotification, sendSlackNotification,
sendTelegramNotification, sendTelegramNotification,
@@ -55,288 +55,295 @@ export const sendBuildSuccessNotifications = async ({
for (const notification of notificationList) { for (const notification of notificationList) {
const { email, discord, telegram, slack, gotify, ntfy, lark } = const { email, discord, telegram, slack, gotify, ntfy, lark } =
notification; notification;
try {
if (email) { if (email) {
const template = await renderAsync( const template = await renderAsync(
BuildSuccessEmail({ BuildSuccessEmail({
projectName, projectName,
applicationName, applicationName,
applicationType, applicationType,
buildLink, buildLink,
date: date.toLocaleString(), date: date.toLocaleString(),
environmentName, environmentName,
}), }),
).catch(); ).catch();
await sendEmailNotification(email, "Build success for dokploy", template); await sendEmailNotification(
} email,
"Build success for dokploy",
if (discord) { template,
const decorate = (decoration: string, text: string) =>
`${discord.decoration ? decoration : ""} ${text}`.trim();
await sendDiscordNotification(discord, {
title: decorate(">", "`✅` Build Successes"),
color: 0x57f287,
fields: [
{
name: decorate("`🛠️`", "Project"),
value: projectName,
inline: true,
},
{
name: decorate("`⚙️`", "Application"),
value: applicationName,
inline: true,
},
{
name: decorate("`🌍`", "Environment"),
value: environmentName,
inline: true,
},
{
name: decorate("`❔`", "Type"),
value: applicationType,
inline: true,
},
{
name: decorate("`📅`", "Date"),
value: `<t:${unixDate}:D>`,
inline: true,
},
{
name: decorate("`⌚`", "Time"),
value: `<t:${unixDate}:t>`,
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("🌍", `Environment: ${environmentName}`)}` +
`${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` +
`🌍Environment: ${environmentName}\n` +
`❔Type: ${applicationType}\n` +
`🕒Date: ${date.toLocaleString()}`,
);
}
if (telegram) {
const chunkArray = <T>(array: T[], chunkSize: number): T[][] =>
Array.from({ length: Math.ceil(array.length / chunkSize) }, (_, i) =>
array.slice(i * chunkSize, i * chunkSize + chunkSize),
); );
}
const inlineButton = [ if (discord) {
[ const decorate = (decoration: string, text: string) =>
{ `${discord.decoration ? decoration : ""} ${text}`.trim();
text: "Deployment Logs",
url: buildLink, await sendDiscordNotification(discord, {
title: decorate(">", "`✅` Build Successes"),
color: 0x57f287,
fields: [
{
name: decorate("`🛠️`", "Project"),
value: projectName,
inline: true,
},
{
name: decorate("`⚙️`", "Application"),
value: applicationName,
inline: true,
},
{
name: decorate("`🌍`", "Environment"),
value: environmentName,
inline: true,
},
{
name: decorate("`❔`", "Type"),
value: applicationType,
inline: true,
},
{
name: decorate("`📅`", "Date"),
value: `<t:${unixDate}:D>`,
inline: true,
},
{
name: decorate("`⌚`", "Time"),
value: `<t:${unixDate}:t>`,
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",
}, },
], });
...chunkArray(domains, 2).map((chunk) => }
chunk.map((data) => ({
text: data.host,
url: `${data.https ? "https" : "http"}://${data.host}`,
})),
),
];
await sendTelegramNotification( if (gotify) {
telegram, const decorate = (decoration: string, text: string) =>
`<b>✅ Build Success</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Environment:</b> ${environmentName}\n<b>Type:</b> ${applicationType}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}`, `${gotify.decoration ? decoration : ""} ${text}\n`;
inlineButton, await sendGotifyNotification(
); gotify,
} decorate("✅", "Build Success"),
`${decorate("🛠️", `Project: ${projectName}`)}` +
`${decorate("⚙️", `Application: ${applicationName}`)}` +
`${decorate("🌍", `Environment: ${environmentName}`)}` +
`${decorate("❔", `Type: ${applicationType}`)}` +
`${decorate("🕒", `Date: ${date.toLocaleString()}`)}` +
`${decorate("🔗", `Build details:\n${buildLink}`)}`,
);
}
if (slack) { if (ntfy) {
const { channel } = slack; await sendNtfyNotification(
await sendSlackNotification(slack, { ntfy,
channel: channel, "Build Success",
attachments: [ "white_check_mark",
{ `view, Build details, ${buildLink}, clear=true;`,
color: "#00FF00", `🛠Project: ${projectName}\n` +
pretext: ":white_check_mark: *Build Success*", `⚙️Application: ${applicationName}\n` +
fields: [ `🌍Environment: ${environmentName}\n` +
{ `❔Type: ${applicationType}\n` +
title: "Project", `🕒Date: ${date.toLocaleString()}`,
value: projectName, );
short: true, }
},
{
title: "Application",
value: applicationName,
short: true,
},
{
title: "Environment",
value: environmentName,
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 (lark) { if (telegram) {
await sendLarkNotification(lark, { const chunkArray = <T>(array: T[], chunkSize: number): T[][] =>
msg_type: "interactive", Array.from({ length: Math.ceil(array.length / chunkSize) }, (_, i) =>
card: { array.slice(i * chunkSize, i * chunkSize + chunkSize),
schema: "2.0", );
config: {
update_multi: true, const inlineButton = [
style: { [
text_size: { {
normal_v2: { text: "Deployment Logs",
default: "normal", url: buildLink,
pc: "normal", },
mobile: "heading", ],
...chunkArray(domains, 2).map((chunk) =>
chunk.map((data) => ({
text: data.host,
url: `${data.https ? "https" : "http"}://${data.host}`,
})),
),
];
await sendTelegramNotification(
telegram,
`<b>✅ Build Success</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Environment:</b> ${environmentName}\n<b>Type:</b> ${applicationType}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${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: "Environment",
value: environmentName,
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 (lark) {
await sendLarkNotification(lark, {
msg_type: "interactive",
card: {
schema: "2.0",
config: {
update_multi: true,
style: {
text_size: {
normal_v2: {
default: "normal",
pc: "normal",
mobile: "heading",
},
}, },
}, },
}, },
}, header: {
header: { title: {
title: { tag: "plain_text",
tag: "plain_text", content: "✅ Build Success",
content: "✅ Build Success",
},
subtitle: {
tag: "plain_text",
content: "",
},
template: "green",
padding: "12px 12px 12px 12px",
},
body: {
direction: "vertical",
padding: "12px 12px 12px 12px",
elements: [
{
tag: "column_set",
columns: [
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Project:**\n${projectName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Environment:**\n${environmentName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Type:**\n${applicationType}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Application:**\n${applicationName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
],
}, },
{ subtitle: {
tag: "button", tag: "plain_text",
text: { content: "",
tag: "plain_text", },
content: "View Build Details", template: "green",
padding: "12px 12px 12px 12px",
},
body: {
direction: "vertical",
padding: "12px 12px 12px 12px",
elements: [
{
tag: "column_set",
columns: [
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Project:**\n${projectName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Environment:**\n${environmentName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Type:**\n${applicationType}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Application:**\n${applicationName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
],
}, },
type: "primary", {
width: "default", tag: "button",
size: "medium", text: {
behaviors: [ tag: "plain_text",
{ content: "View Build Details",
type: "open_url",
default_url: buildLink,
pc_url: "",
ios_url: "",
android_url: "",
}, },
], type: "primary",
margin: "0px 0px 0px 0px", width: "default",
}, size: "medium",
], behaviors: [
{
type: "open_url",
default_url: buildLink,
pc_url: "",
ios_url: "",
android_url: "",
},
],
margin: "0px 0px 0px 0px",
},
],
},
}, },
}, });
}); }
} catch (error) {
console.log(error);
} }
} }
}; };
@@ -7,8 +7,8 @@ import { and, eq } from "drizzle-orm";
import { import {
sendDiscordNotification, sendDiscordNotification,
sendEmailNotification, sendEmailNotification,
sendLarkNotification,
sendGotifyNotification, sendGotifyNotification,
sendLarkNotification,
sendNtfyNotification, sendNtfyNotification,
sendSlackNotification, sendSlackNotification,
sendTelegramNotification, sendTelegramNotification,
@@ -52,309 +52,312 @@ export const sendDatabaseBackupNotifications = async ({
for (const notification of notificationList) { for (const notification of notificationList) {
const { email, discord, telegram, slack, gotify, ntfy, lark } = const { email, discord, telegram, slack, gotify, ntfy, lark } =
notification; notification;
try {
if (email) {
const template = await renderAsync(
DatabaseBackupEmail({
projectName,
applicationName,
databaseType,
type,
errorMessage,
date: date.toLocaleString(),
}),
).catch();
await sendEmailNotification(
email,
"Database backup for dokploy",
template,
);
}
if (email) { if (discord) {
const template = await renderAsync( const decorate = (decoration: string, text: string) =>
DatabaseBackupEmail({ `${discord.decoration ? decoration : ""} ${text}`.trim();
projectName,
applicationName,
databaseType,
type,
errorMessage,
date: date.toLocaleString(),
}),
).catch();
await sendEmailNotification(
email,
"Database backup for dokploy",
template,
);
}
if (discord) { await sendDiscordNotification(discord, {
const decorate = (decoration: string, text: string) => title:
`${discord.decoration ? decoration : ""} ${text}`.trim(); type === "success"
? decorate(">", "`✅` Database Backup Successful")
: decorate(">", "`❌` Database Backup Failed"),
color: type === "success" ? 0x57f287 : 0xed4245,
fields: [
{
name: decorate("`🛠️`", "Project"),
value: projectName,
inline: true,
},
{
name: decorate("`⚙️`", "Application"),
value: applicationName,
inline: true,
},
{
name: decorate("`❔`", "Database"),
value: databaseType,
inline: true,
},
{
name: decorate("`📂`", "Database Name"),
value: databaseName,
inline: true,
},
{
name: decorate("`📅`", "Date"),
value: `<t:${unixDate}:D>`,
inline: true,
},
{
name: decorate("`⌚`", "Time"),
value: `<t:${unixDate}:t>`,
inline: true,
},
{
name: decorate("`❓`", "Type"),
value: type
.replace("error", "Failed")
.replace("success", "Successful"),
inline: true,
},
...(type === "error" && errorMessage
? [
{
name: decorate("`⚠️`", "Error Message"),
value: `\`\`\`${errorMessage}\`\`\``,
},
]
: []),
],
timestamp: date.toISOString(),
footer: {
text: "Dokploy Database Backup Notification",
},
});
}
await sendDiscordNotification(discord, { if (gotify) {
title: const decorate = (decoration: string, text: string) =>
type === "success" `${gotify.decoration ? decoration : ""} ${text}\n`;
? decorate(">", "`✅` Database Backup Successful")
: decorate(">", "`❌` Database Backup Failed"),
color: type === "success" ? 0x57f287 : 0xed4245,
fields: [
{
name: decorate("`🛠️`", "Project"),
value: projectName,
inline: true,
},
{
name: decorate("`⚙️`", "Application"),
value: applicationName,
inline: true,
},
{
name: decorate("`❔`", "Database"),
value: databaseType,
inline: true,
},
{
name: decorate("`📂`", "Database Name"),
value: databaseName,
inline: true,
},
{
name: decorate("`📅`", "Date"),
value: `<t:${unixDate}:D>`,
inline: true,
},
{
name: decorate("`⌚`", "Time"),
value: `<t:${unixDate}:t>`,
inline: true,
},
{
name: decorate("`❓`", "Type"),
value: type
.replace("error", "Failed")
.replace("success", "Successful"),
inline: true,
},
...(type === "error" && errorMessage
? [
{
name: decorate("`⚠️`", "Error Message"),
value: `\`\`\`${errorMessage}\`\`\``,
},
]
: []),
],
timestamp: date.toISOString(),
footer: {
text: "Dokploy Database Backup Notification",
},
});
}
if (gotify) { await sendGotifyNotification(
const decorate = (decoration: string, text: string) => gotify,
`${gotify.decoration ? decoration : ""} ${text}\n`; decorate(
type === "success" ? "✅" : "❌",
`Database Backup ${type === "success" ? "Successful" : "Failed"}`,
),
`${decorate("🛠️", `Project: ${projectName}`)}` +
`${decorate("⚙️", `Application: ${applicationName}`)}` +
`${decorate("❔", `Type: ${databaseType}`)}` +
`${decorate("📂", `Database Name: ${databaseName}`)}` +
`${decorate("🕒", `Date: ${date.toLocaleString()}`)}` +
`${type === "error" && errorMessage ? decorate("❌", `Error:\n${errorMessage}`) : ""}`,
);
}
await sendGotifyNotification( if (ntfy) {
gotify, await sendNtfyNotification(
decorate( ntfy,
type === "success" ? "✅" : "❌",
`Database Backup ${type === "success" ? "Successful" : "Failed"}`, `Database Backup ${type === "success" ? "Successful" : "Failed"}`,
), `${type === "success" ? "white_check_mark" : "x"}`,
`${decorate("🛠️", `Project: ${projectName}`)}` + "",
`${decorate("⚙️", `Application: ${applicationName}`)}` + `🛠Project: ${projectName}\n` +
`${decorate("❔", `Type: ${databaseType}`)}` + `⚙️Application: ${applicationName}\n` +
`${decorate("📂", `Database Name: ${databaseName}`)}` + `❔Type: ${databaseType}\n` +
`${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + `📂Database Name: ${databaseName}` +
`${type === "error" && errorMessage ? decorate("❌", `Error:\n${errorMessage}`) : ""}`, `🕒Date: ${date.toLocaleString()}\n` +
); `${type === "error" && errorMessage ? `❌Error:\n${errorMessage}` : ""}`,
} );
}
if (ntfy) { if (telegram) {
await sendNtfyNotification( const isError = type === "error" && errorMessage;
ntfy,
`Database Backup ${type === "success" ? "Successful" : "Failed"}`,
`${type === "success" ? "white_check_mark" : "x"}`,
"",
`🛠Project: ${projectName}\n` +
`⚙️Application: ${applicationName}\n` +
`❔Type: ${databaseType}\n` +
`📂Database Name: ${databaseName}` +
`🕒Date: ${date.toLocaleString()}\n` +
`${type === "error" && errorMessage ? `❌Error:\n${errorMessage}` : ""}`,
);
}
if (telegram) { const statusEmoji = type === "success" ? "✅" : "❌";
const isError = type === "error" && errorMessage; const typeStatus = type === "success" ? "Successful" : "Failed";
const errorMsg = isError
? `\n\n<b>Error:</b>\n<pre>${errorMessage}</pre>`
: "";
const statusEmoji = type === "success" ? "✅" : "❌"; const messageText = `<b>${statusEmoji} Database Backup ${typeStatus}</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Type:</b> ${databaseType}\n<b>Database Name:</b> ${databaseName}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}${isError ? errorMsg : ""}`;
const typeStatus = type === "success" ? "Successful" : "Failed";
const errorMsg = isError
? `\n\n<b>Error:</b>\n<pre>${errorMessage}</pre>`
: "";
const messageText = `<b>${statusEmoji} Database Backup ${typeStatus}</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Type:</b> ${databaseType}\n<b>Database Name:</b> ${databaseName}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}${isError ? errorMsg : ""}`; await sendTelegramNotification(telegram, messageText);
}
await sendTelegramNotification(telegram, messageText); if (slack) {
} const { channel } = slack;
await sendSlackNotification(slack, {
channel: channel,
attachments: [
{
color: type === "success" ? "#00FF00" : "#FF0000",
pretext:
type === "success"
? ":white_check_mark: *Database Backup Successful*"
: ":x: *Database Backup Failed*",
fields: [
...(type === "error" && errorMessage
? [
{
title: "Error Message",
value: errorMessage,
short: false,
},
]
: []),
{
title: "Project",
value: projectName,
short: true,
},
{
title: "Application",
value: applicationName,
short: true,
},
{
title: "Type",
value: databaseType,
short: true,
},
{
title: "Database Name",
value: databaseName,
},
{
title: "Time",
value: date.toLocaleString(),
short: true,
},
{
title: "Type",
value: type,
},
{
title: "Status",
value: type === "success" ? "Successful" : "Failed",
},
],
},
],
});
}
if (slack) { if (lark) {
const { channel } = slack; const limitCharacter = 800;
await sendSlackNotification(slack, { const truncatedErrorMessage =
channel: channel, errorMessage && errorMessage.length > limitCharacter
attachments: [ ? errorMessage.substring(0, limitCharacter)
{ : errorMessage;
color: type === "success" ? "#00FF00" : "#FF0000",
pretext:
type === "success"
? ":white_check_mark: *Database Backup Successful*"
: ":x: *Database Backup Failed*",
fields: [
...(type === "error" && errorMessage
? [
{
title: "Error Message",
value: errorMessage,
short: false,
},
]
: []),
{
title: "Project",
value: projectName,
short: true,
},
{
title: "Application",
value: applicationName,
short: true,
},
{
title: "Type",
value: databaseType,
short: true,
},
{
title: "Database Name",
value: databaseName,
},
{
title: "Time",
value: date.toLocaleString(),
short: true,
},
{
title: "Type",
value: type,
},
{
title: "Status",
value: type === "success" ? "Successful" : "Failed",
},
],
},
],
});
}
if (lark) { await sendLarkNotification(lark, {
const limitCharacter = 800; msg_type: "interactive",
const truncatedErrorMessage = card: {
errorMessage && errorMessage.length > limitCharacter schema: "2.0",
? errorMessage.substring(0, limitCharacter) config: {
: errorMessage; update_multi: true,
style: {
await sendLarkNotification(lark, { text_size: {
msg_type: "interactive", normal_v2: {
card: { default: "normal",
schema: "2.0", pc: "normal",
config: { mobile: "heading",
update_multi: true, },
style: {
text_size: {
normal_v2: {
default: "normal",
pc: "normal",
mobile: "heading",
}, },
}, },
}, },
}, header: {
header: { title: {
title: { tag: "plain_text",
tag: "plain_text", content:
content: type === "success"
type === "success" ? "✅ Database Backup Successful"
? "✅ Database Backup Successful" : "❌ Database Backup Failed",
: "❌ Database Backup Failed",
},
subtitle: {
tag: "plain_text",
content: "",
},
template: type === "success" ? "green" : "red",
padding: "12px 12px 12px 12px",
},
body: {
direction: "vertical",
padding: "12px 12px 12px 12px",
elements: [
{
tag: "column_set",
columns: [
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Project:**\n${projectName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Database Type:**\n${databaseType}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Status:**\n${type === "success" ? "Successful" : "Failed"}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Application:**\n${applicationName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Database Name:**\n${databaseName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
],
}, },
...(type === "error" && truncatedErrorMessage subtitle: {
? [ tag: "plain_text",
content: "",
},
template: type === "success" ? "green" : "red",
padding: "12px 12px 12px 12px",
},
body: {
direction: "vertical",
padding: "12px 12px 12px 12px",
elements: [
{
tag: "column_set",
columns: [
{ {
tag: "markdown", tag: "column",
content: `**Error Message:**\n\`\`\`\n${truncatedErrorMessage}\n\`\`\``, width: "weighted",
text_align: "left", elements: [
text_size: "normal_v2", {
tag: "markdown",
content: `**Project:**\n${projectName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Database Type:**\n${databaseType}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Status:**\n${type === "success" ? "Successful" : "Failed"}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
}, },
] {
: []), tag: "column",
], width: "weighted",
elements: [
{
tag: "markdown",
content: `**Application:**\n${applicationName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Database Name:**\n${databaseName}`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
],
},
...(type === "error" && truncatedErrorMessage
? [
{
tag: "markdown",
content: `**Error Message:**\n\`\`\`\n${truncatedErrorMessage}\n\`\`\``,
text_align: "left",
text_size: "normal_v2",
},
]
: []),
],
},
}, },
}, });
}); }
} catch (error) {
console.log(error);
} }
} }
}; };
@@ -7,8 +7,8 @@ import { and, eq } from "drizzle-orm";
import { import {
sendDiscordNotification, sendDiscordNotification,
sendEmailNotification, sendEmailNotification,
sendLarkNotification,
sendGotifyNotification, sendGotifyNotification,
sendLarkNotification,
sendNtfyNotification, sendNtfyNotification,
sendSlackNotification, sendSlackNotification,
sendTelegramNotification, sendTelegramNotification,
@@ -39,182 +39,185 @@ export const sendDockerCleanupNotifications = async (
for (const notification of notificationList) { for (const notification of notificationList) {
const { email, discord, telegram, slack, gotify, ntfy, lark } = const { email, discord, telegram, slack, gotify, ntfy, lark } =
notification; notification;
try {
if (email) {
const template = await renderAsync(
DockerCleanupEmail({ message, date: date.toLocaleString() }),
).catch();
if (email) { await sendEmailNotification(
const template = await renderAsync( email,
DockerCleanupEmail({ message, date: date.toLocaleString() }), "Docker cleanup for dokploy",
).catch(); template,
);
}
await sendEmailNotification( if (discord) {
email, const decorate = (decoration: string, text: string) =>
"Docker cleanup for dokploy", `${discord.decoration ? decoration : ""} ${text}`.trim();
template,
);
}
if (discord) { await sendDiscordNotification(discord, {
const decorate = (decoration: string, text: string) => title: decorate(">", "`✅` Docker Cleanup"),
`${discord.decoration ? decoration : ""} ${text}`.trim(); color: 0x57f287,
fields: [
await sendDiscordNotification(discord, { {
title: decorate(">", "`✅` Docker Cleanup"), name: decorate("`📅`", "Date"),
color: 0x57f287, value: `<t:${unixDate}:D>`,
fields: [ inline: true,
{ },
name: decorate("`📅`", "Date"), {
value: `<t:${unixDate}:D>`, name: decorate("`⌚`", "Time"),
inline: true, value: `<t:${unixDate}:t>`,
inline: true,
},
{
name: decorate("`❓`", "Type"),
value: "Successful",
inline: true,
},
{
name: decorate("`📜`", "Message"),
value: `\`\`\`${message}\`\`\``,
},
],
timestamp: date.toISOString(),
footer: {
text: "Dokploy Docker Cleanup Notification",
}, },
{ });
name: decorate("`⌚`", "Time"), }
value: `<t:${unixDate}:t>`,
inline: true,
},
{
name: decorate("`❓`", "Type"),
value: "Successful",
inline: true,
},
{
name: decorate("`📜`", "Message"),
value: `\`\`\`${message}\`\`\``,
},
],
timestamp: date.toISOString(),
footer: {
text: "Dokploy Docker Cleanup Notification",
},
});
}
if (gotify) { if (gotify) {
const decorate = (decoration: string, text: string) => const decorate = (decoration: string, text: string) =>
`${gotify.decoration ? decoration : ""} ${text}\n`; `${gotify.decoration ? decoration : ""} ${text}\n`;
await sendGotifyNotification( await sendGotifyNotification(
gotify, gotify,
decorate("✅", "Docker Cleanup"), decorate("✅", "Docker Cleanup"),
`${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + `${decorate("🕒", `Date: ${date.toLocaleString()}`)}` +
`${decorate("📜", `Message:\n${message}`)}`, `${decorate("📜", `Message:\n${message}`)}`,
); );
} }
if (ntfy) { if (ntfy) {
await sendNtfyNotification( await sendNtfyNotification(
ntfy, ntfy,
"Docker Cleanup", "Docker Cleanup",
"white_check_mark", "white_check_mark",
"", "",
`🕒Date: ${date.toLocaleString()}\n` + `📜Message:\n${message}`, `🕒Date: ${date.toLocaleString()}\n` + `📜Message:\n${message}`,
); );
} }
if (telegram) { if (telegram) {
await sendTelegramNotification( await sendTelegramNotification(
telegram, telegram,
`<b>✅ Docker Cleanup</b>\n\n<b>Message:</b> ${message}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}`, `<b>✅ Docker Cleanup</b>\n\n<b>Message:</b> ${message}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}`,
); );
} }
if (slack) { if (slack) {
const { channel } = slack; const { channel } = slack;
await sendSlackNotification(slack, { await sendSlackNotification(slack, {
channel: channel, channel: channel,
attachments: [ attachments: [
{ {
color: "#00FF00", color: "#00FF00",
pretext: ":white_check_mark: *Docker Cleanup*", pretext: ":white_check_mark: *Docker Cleanup*",
fields: [ fields: [
{ {
title: "Message", title: "Message",
value: message, value: message,
}, },
{ {
title: "Time", title: "Time",
value: date.toLocaleString(), value: date.toLocaleString(),
short: true, short: true,
}, },
], ],
}, },
], ],
}); });
} }
if (lark) { if (lark) {
await sendLarkNotification(lark, { await sendLarkNotification(lark, {
msg_type: "interactive", msg_type: "interactive",
card: { card: {
schema: "2.0", schema: "2.0",
config: { config: {
update_multi: true, update_multi: true,
style: { style: {
text_size: { text_size: {
normal_v2: { normal_v2: {
default: "normal", default: "normal",
pc: "normal", pc: "normal",
mobile: "heading", mobile: "heading",
},
}, },
}, },
}, },
}, header: {
header: { title: {
title: { tag: "plain_text",
tag: "plain_text", content: "✅ Docker Cleanup",
content: "✅ Docker Cleanup",
},
subtitle: {
tag: "plain_text",
content: "",
},
template: "green",
padding: "12px 12px 12px 12px",
},
body: {
direction: "vertical",
padding: "12px 12px 12px 12px",
elements: [
{
tag: "column_set",
columns: [
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Status:**\nSuccessful`,
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Cleanup Details:**\n${message}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
],
}, },
], subtitle: {
tag: "plain_text",
content: "",
},
template: "green",
padding: "12px 12px 12px 12px",
},
body: {
direction: "vertical",
padding: "12px 12px 12px 12px",
elements: [
{
tag: "column_set",
columns: [
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: "**Status:**\nSuccessful",
text_align: "left",
text_size: "normal_v2",
},
{
tag: "markdown",
content: `**Cleanup Details:**\n${message}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
{
tag: "column",
width: "weighted",
elements: [
{
tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left",
text_size: "normal_v2",
},
],
vertical_align: "top",
weight: 1,
},
],
},
],
},
}, },
}, });
}); }
} catch (error) {
console.log(error);
} }
} }
}; };
@@ -7,8 +7,8 @@ import { eq } from "drizzle-orm";
import { import {
sendDiscordNotification, sendDiscordNotification,
sendEmailNotification, sendEmailNotification,
sendLarkNotification,
sendGotifyNotification, sendGotifyNotification,
sendLarkNotification,
sendNtfyNotification, sendNtfyNotification,
sendSlackNotification, sendSlackNotification,
sendTelegramNotification, sendTelegramNotification,
@@ -34,18 +34,23 @@ export const sendDokployRestartNotifications = async () => {
const { email, discord, telegram, slack, gotify, ntfy, lark } = const { email, discord, telegram, slack, gotify, ntfy, lark } =
notification; notification;
if (email) { try {
const template = await renderAsync( if (email) {
DokployRestartEmail({ date: date.toLocaleString() }), const template = await renderAsync(
).catch(); DokployRestartEmail({ date: date.toLocaleString() }),
await sendEmailNotification(email, "Dokploy Server Restarted", template); ).catch();
}
if (discord) { await sendEmailNotification(
const decorate = (decoration: string, text: string) => email,
`${discord.decoration ? decoration : ""} ${text}`.trim(); "Dokploy Server Restarted",
template,
);
}
if (discord) {
const decorate = (decoration: string, text: string) =>
`${discord.decoration ? decoration : ""} ${text}`.trim();
try {
await sendDiscordNotification(discord, { await sendDiscordNotification(discord, {
title: decorate(">", "`✅` Dokploy Server Restarted"), title: decorate(">", "`✅` Dokploy Server Restarted"),
color: 0x57f287, color: 0x57f287,
@@ -71,27 +76,19 @@ export const sendDokployRestartNotifications = async () => {
text: "Dokploy Restart Notification", text: "Dokploy Restart Notification",
}, },
}); });
} catch (error) {
console.log(error);
} }
}
if (gotify) { if (gotify) {
const decorate = (decoration: string, text: string) => const decorate = (decoration: string, text: string) =>
`${gotify.decoration ? decoration : ""} ${text}\n`; `${gotify.decoration ? decoration : ""} ${text}\n`;
try {
await sendGotifyNotification( await sendGotifyNotification(
gotify, gotify,
decorate("✅", "Dokploy Server Restarted"), decorate("✅", "Dokploy Server Restarted"),
`${decorate("🕒", `Date: ${date.toLocaleString()}`)}`, `${decorate("🕒", `Date: ${date.toLocaleString()}`)}`,
); );
} catch (error) {
console.log(error);
} }
}
if (ntfy) { if (ntfy) {
try {
await sendNtfyNotification( await sendNtfyNotification(
ntfy, ntfy,
"Dokploy Server Restarted", "Dokploy Server Restarted",
@@ -99,25 +96,17 @@ export const sendDokployRestartNotifications = async () => {
"", "",
`🕒Date: ${date.toLocaleString()}`, `🕒Date: ${date.toLocaleString()}`,
); );
} catch (error) {
console.log(error);
} }
}
if (telegram) { if (telegram) {
try {
await sendTelegramNotification( await sendTelegramNotification(
telegram, telegram,
`<b>✅ Dokploy Server Restarted</b>\n\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}`, `<b>✅ Dokploy Server Restarted</b>\n\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}`,
); );
} catch (error) {
console.log(error);
} }
}
if (slack) { if (slack) {
const { channel } = slack; const { channel } = slack;
try {
await sendSlackNotification(slack, { await sendSlackNotification(slack, {
channel: channel, channel: channel,
attachments: [ attachments: [
@@ -134,13 +123,9 @@ export const sendDokployRestartNotifications = async () => {
}, },
], ],
}); });
} catch (error) {
console.log(error);
} }
}
if (lark) { if (lark) {
try {
await sendLarkNotification(lark, { await sendLarkNotification(lark, {
msg_type: "interactive", msg_type: "interactive",
card: { card: {
@@ -182,7 +167,7 @@ export const sendDokployRestartNotifications = async () => {
elements: [ elements: [
{ {
tag: "markdown", tag: "markdown",
content: `**Status:**\nSuccessful`, content: "**Status:**\nSuccessful",
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
@@ -210,9 +195,9 @@ export const sendDokployRestartNotifications = async () => {
}, },
}, },
}); });
} catch (error) {
console.log(error);
} }
} catch (error) {
console.log(error);
} }
} }
}; };
@@ -1,8 +1,8 @@
import type { import type {
discord, discord,
email, email,
lark,
gotify, gotify,
lark,
ntfy, ntfy,
slack, slack,
telegram, telegram,
@@ -38,6 +38,9 @@ export const sendEmailNotification = async (
}); });
} catch (err) { } catch (err) {
console.log(err); console.log(err);
throw new Error(
`Failed to send email notification ${err instanceof Error ? err.message : "Unknown error"}`,
);
} }
}; };
@@ -45,15 +48,23 @@ export const sendDiscordNotification = async (
connection: typeof discord.$inferInsert, connection: typeof discord.$inferInsert,
embed: any, embed: any,
) => { ) => {
// try { try {
await fetch(connection.webhookUrl, { const response = await fetch(connection.webhookUrl, {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ embeds: [embed] }), body: JSON.stringify({ embeds: [embed] }),
}); });
// } catch (err) { if (!response.ok) {
// console.log(err); throw new Error(
// } `Failed to send discord notification ${response.statusText}`,
);
}
} catch (err) {
console.log("error", err);
throw new Error(
`Failed to send discord notification ${err instanceof Error ? err.message : "Unknown error"}`,
);
}
}; };
export const sendTelegramNotification = async ( export const sendTelegramNotification = async (
@@ -90,13 +101,21 @@ export const sendSlackNotification = async (
message: any, message: any,
) => { ) => {
try { try {
await fetch(connection.webhookUrl, { const response = await fetch(connection.webhookUrl, {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify(message), body: JSON.stringify(message),
}); });
if (!response.ok) {
throw new Error(
`Failed to send slack notification ${response.statusText}`,
);
}
} catch (err) { } catch (err) {
console.log(err); console.log("error", err);
throw new Error(
`Failed to send slack notification ${err instanceof Error ? err.message : "Unknown error"}`,
);
} }
}; };