Skip to content

Commit

Permalink
Implemented code reuse and smooth error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Aspasht committed Sep 5, 2024
1 parent b9bce82 commit 0a5864e
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 150 deletions.
47 changes: 4 additions & 43 deletions src/notifiers/CustomNotifier.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,11 @@
import Log from "../constants/Log";
import { Notifier } from "./Notifier";

export class CustomNotifier extends Notifier {
private message: string = "";

constructor(private readonly webhookUrl: string) {
super();
this.webhookUrl = webhookUrl;
}

validate() {
if (!this.webhookUrl) {
Log.error("Custom webhook url is not set");
throw new Error("[-] Custom webhook url is not set");
}

const newUrl = new URL(this.webhookUrl);
if (newUrl.protocol !== "http:" && newUrl.protocol !== "https:") {
throw new Error("[-] Custom webhook url is invalid. ");
}
constructor(webhookUrl: string, message: string) {
super(webhookUrl, message);
}

async notify(message?: string) {
if (message) {
this.message = message;
}
this.validate();
const webhookMessage = {
content: this.message,
};
try {
await fetch(this.webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(webhookMessage),
});
console.log("[+] Notification successfully sent to slack");
} catch (error) {
console.error(error);
}
sendNotification(): void {
this.notify();
}

withMessage(message: string) {
this.message = message;
return this;
}
}
47 changes: 4 additions & 43 deletions src/notifiers/DiscordNotifier.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,11 @@
import Log from "../constants/Log";
import { Notifier } from "./Notifier";

export class DiscordNotifier extends Notifier {
private message: string = "";

constructor(private readonly webhookUrl: string) {
super();
this.webhookUrl = webhookUrl;
}

validate() {
if (!this.webhookUrl) {
Log.error("Discord_URL is not set");
throw new Error("[-] Discord_URL is not set");
}

const newUrl = new URL(this.webhookUrl);
if (newUrl.protocol !== "http:" && newUrl.protocol !== "https:") {
throw new Error("[-] Discord webhook url is invalid. ");
}
constructor(webhookUrl: string, message: string) {
super(webhookUrl, message);
}

async notify(message?: string) {
if (message) {
this.message = message;
}
this.validate();
const webhookMessage = {
content: this.message,
};
try {
await fetch(this.webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(webhookMessage),
});
console.log("[+] Notification successfully sent to discord.");
} catch (error) {
console.error(error);
}
sendNotification(): void {
this.notify();
}

withMessage(message: string) {
this.message = message;
return this;
}
}
50 changes: 46 additions & 4 deletions src/notifiers/Notifier.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,50 @@
/* eslint-disable no-unused-vars */
import Log from "../constants/Log";

export abstract class Notifier {
abstract validate(): void;
abstract notify(message?: string): void;
}
protected webhookUrl: string;
protected message: string;

constructor(webhookUrl: string, message: string) {
this.webhookUrl = webhookUrl;
this.message = message;
}

abstract sendNotification(): void;

validate(): void {
if (!this.webhookUrl) {
throw new Error("[-] Webhook URL is not set");
}

const newUrl = new URL(this.webhookUrl);
if (newUrl.protocol !== "http:" && newUrl.protocol !== "https:") {
throw new Error("[-] Webhook URL is invalid.");
}
}

async notify(): Promise<void> {
try {
const response = await fetch(this.webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
content: this.message
})
});

if (!response.ok) {
console.error(`[-] Failed to send notification to ${new URL(this.webhookUrl).hostname.replace('.com',"")}: ${response.status} ${response.statusText} `);
} else {
console.log(`[+] Notification sent successfully to ${new URL(this.webhookUrl).hostname.replace('.com',"")}`);
}
} catch (error) {
Log.error(`Error sending notification: ${error}`)
console.error(`[-] Error sending notification: ${error}`);
}
}
}

export interface NotifierOption {
databaseName: string;
Expand Down
47 changes: 4 additions & 43 deletions src/notifiers/SlackNotifier.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,11 @@
import Log from "../constants/Log";
import { Notifier } from "./Notifier";

export class SlackNotifier extends Notifier {
private message: string = "";

constructor(private readonly webhookUrl: string) {
super();
this.webhookUrl = webhookUrl;
}

validate() {
if (!this.webhookUrl) {
Log.error("WEBHOOK_URL is not set");
throw new Error("[-] WEBHOOK_URL is not set");
}

const newUrl = new URL(this.webhookUrl);
if (newUrl.protocol !== "http:" && newUrl.protocol !== "https:") {
throw new Error("[-] Webhook url is invalid. ");
}
constructor(webhookUrl: string, message: string) {
super(webhookUrl, message);
}

async notify(message?: string) {
if (message) {
this.message = message;
}
this.validate();
const webhookMessage = {
content: this.message,
};
try {
await fetch(this.webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(webhookMessage),
});
console.log("[+] Notification successfully sent");
} catch (error) {
console.error(error);
}
sendNotification(): void {
this.notify();
}

withMessage(message: string) {
this.message = message;
return this;
}
}
31 changes: 14 additions & 17 deletions src/utils/notify.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,29 @@ import { Notifier, NotifierOption } from "../notifiers/Notifier";
import { SlackNotifier } from "../notifiers/SlackNotifier";
import { DiscordNotifier } from "../notifiers/DiscordNotifier";


export const sendNotification = async (
mediums: string,
option: NotifierOption
) => {
const notify_on = mediums.split(",") as NotifyOnMedium[];
const notifiers: Notifier[] = [];
const message = `Backup completed successfully for database: ${option.databaseName} at ${new Date()}`
for (const medium of notify_on) {
switch (medium.trim().toUpperCase()) {
case "SLACK":
notifiers.push(
new SlackNotifier(EnvConfig.SLACK_WEBHOOK_URL!).withMessage(
`Backup completed successfully for database: ${
option.databaseName
} at ${new Date()}`
)
new SlackNotifier(EnvConfig.SLACK_WEBHOOK_URL!,message)
);
break;
case "DISCORD":
notifiers.push(
new DiscordNotifier(EnvConfig.DISCORD_WEBHOOK_URL!).withMessage(
`Backup completed successfully for database: ${
option.databaseName
} at ${new Date()}`
)
new DiscordNotifier(EnvConfig.DISCORD_WEBHOOK_URL!,message)
);
break;
case "CUSTOM":
notifiers.push(
new CustomNotifier(EnvConfig.CUSTOM_WEBHOOK_URL!).withMessage(
`Backup completed successfully for database: ${
option.databaseName
} at ${new Date()}`
)
new CustomNotifier(EnvConfig.CUSTOM_WEBHOOK_URL!,message)
);
break;
default:
Expand All @@ -54,8 +44,15 @@ export const sendNotification = async (
function notifyAllMedium(notifiers: Notifier[]) {
return async () => {
for (const notifier of notifiers) {
notifier.notify();
}
try {
notifier.validate();
await notifier.sendNotification();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error:any) {
Log.error(`Validation or notification error: ${error.message}`);
console.error(`[-] Validation or notification error: ${error.message}`);
}
};
}
}

0 comments on commit 0a5864e

Please sign in to comment.