From 0a5864e4c1de2e41f941ad27054eaee671a8cb0d Mon Sep 17 00:00:00 2001 From: sagar pariyar <72987297+Aspasht@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:27:26 +0300 Subject: [PATCH] Implemented code reuse and smooth error handling --- src/notifiers/CustomNotifier.ts | 47 +++--------------------------- src/notifiers/DiscordNotifier.ts | 47 +++--------------------------- src/notifiers/Notifier.ts | 50 +++++++++++++++++++++++++++++--- src/notifiers/SlackNotifier.ts | 47 +++--------------------------- src/utils/notify.utils.ts | 31 +++++++++----------- 5 files changed, 72 insertions(+), 150 deletions(-) diff --git a/src/notifiers/CustomNotifier.ts b/src/notifiers/CustomNotifier.ts index e96cae2..e372cae 100644 --- a/src/notifiers/CustomNotifier.ts +++ b/src/notifiers/CustomNotifier.ts @@ -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; - } } diff --git a/src/notifiers/DiscordNotifier.ts b/src/notifiers/DiscordNotifier.ts index 19a60fc..5982f7d 100644 --- a/src/notifiers/DiscordNotifier.ts +++ b/src/notifiers/DiscordNotifier.ts @@ -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; - } } diff --git a/src/notifiers/Notifier.ts b/src/notifiers/Notifier.ts index 42856df..355bad6 100644 --- a/src/notifiers/Notifier.ts +++ b/src/notifiers/Notifier.ts @@ -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 { + 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; diff --git a/src/notifiers/SlackNotifier.ts b/src/notifiers/SlackNotifier.ts index 417775e..0a5184a 100644 --- a/src/notifiers/SlackNotifier.ts +++ b/src/notifiers/SlackNotifier.ts @@ -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; - } } diff --git a/src/utils/notify.utils.ts b/src/utils/notify.utils.ts index 876e22d..f3501ef 100644 --- a/src/utils/notify.utils.ts +++ b/src/utils/notify.utils.ts @@ -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: @@ -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}`); + } }; } +}