Skip to content

Commit

Permalink
Webhook notifier (#380)
Browse files Browse the repository at this point in the history
Generic webhook notifier

---------

Co-authored-by: charlocharlie <[email protected]>
  • Loading branch information
MiguelAngelLV and claabs authored Feb 23, 2024
1 parent 2734e6b commit 734c18d
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 1 deletion.
9 changes: 9 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ The config file is stored in the mounted `/usr/app/config` volume and can be nam
"priority": "urgent",
"token": "tk_mytoken"
},
{
"type":"webhook",
//url of your webhook server
"url":"https://webhook.site/my_uuid",
//Optional headers
"headers": {
"Authentication": "Bearer 123456"
}
},
],
}
```
Expand Down
47 changes: 46 additions & 1 deletion src/common/config/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export enum NotificationType {
HOMEASSISTANT = 'homeassistant',
BARK = 'bark',
NTFY = 'ntfy',
WEBHOOK = 'webhook',
}

/**
Expand Down Expand Up @@ -497,6 +498,34 @@ export class BarkConfig extends NotifierConfig {
}
}

/**
* Sends a POST request with the notification contents in the body to a [webhook](https://en.wikipedia.org/wiki/Webhook) URL
*/
export class WebhookConfig extends NotifierConfig {
/**
* Webhook URL
* @env WEBHOOK_URL
*/
@IsUrl({ require_tld: false })
url: string;

/**
* A key-value pair object to pass into the POST request headers
* @example { Authorization: "Bearer ABCD" }
* @env WEBHOOK_HEADERS (stringified JSON)
*/
@IsObject()
@IsOptional()
headers: Record<string, string> | undefined;

/**
* @ignore
*/
constructor() {
super(NotificationType.WEBHOOK);
}
}

export type AnyNotifierConfig =
| EmailConfig
| DiscordConfig
Expand All @@ -508,7 +537,8 @@ export type AnyNotifierConfig =
| SlackConfig
| HomeassistantConfig
| BarkConfig
| NtfyConfig;
| NtfyConfig
| WebhookConfig;

const notifierSubtypes: {
value: ClassConstructor<NotifierConfig>;
Expand All @@ -525,6 +555,7 @@ const notifierSubtypes: {
{ value: HomeassistantConfig, name: NotificationType.HOMEASSISTANT },
{ value: BarkConfig, name: NotificationType.BARK },
{ value: NtfyConfig, name: NotificationType.NTFY },
{ value: WebhookConfig, name: NotificationType.WEBHOOK },
];

export class WebPortalConfig {
Expand Down Expand Up @@ -1135,6 +1166,20 @@ export class AppConfig {
}
}

// Use environment variables to fill webhook notification config if present
const { WEBHOOK_URL, WEBHOOK_HEADERS } = process.env;
if (WEBHOOK_URL) {
const webhook = new WebhookConfig();
webhook.url = WEBHOOK_URL;
webhook.headers = WEBHOOK_HEADERS ? JSON.parse(WEBHOOK_HEADERS) : undefined;
if (!this.notifiers) {
this.notifiers = [];
}
if (!this.notifiers.some((notifConfig) => notifConfig instanceof WebhookConfig)) {
this.notifiers.push(webhook);
}
}

// Use environment variables to fill webPortalConfig if present
const { BASE_URL, SERVER_PORT } = process.env;
if (BASE_URL) {
Expand Down
1 change: 1 addition & 0 deletions src/notifiers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './slack';
export * from './bark';
export * from './ntfy';
export * from './homeassistant';
export * from './webhook';
41 changes: 41 additions & 0 deletions src/notifiers/webhook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import axios from 'axios';
import logger from '../common/logger';
import { NotifierService } from './notifier-service';
import { NotificationReason } from '../interfaces/notification-reason';
import { WebhookConfig } from '../common/config';

export class WebhookNotifier extends NotifierService {
private config: WebhookConfig;

constructor(config: WebhookConfig) {
super();
this.config = config;
}

async sendNotification(account: string, reason: NotificationReason, url?: string): Promise<void> {
const L = logger.child({ user: account, reason });
L.trace('Sending webhook notification');

try {
await axios.post(
this.config.url,
{
account,
reason,
url,
},
{
responseType: 'json',
headers: this.config.headers,
}
);
} catch (err) {
L.error(err);
L.error(
{ webhookConfig: this.config },
'Error sending webhook message. Please check your configuration'
);
throw err;
}
}
}
4 changes: 4 additions & 0 deletions src/notify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
NtfyNotifier,
PushoverNotifier,
HomeassistantNotifier,
WebhookNotifier,
} from './notifiers';
import {
config,
Expand All @@ -25,6 +26,7 @@ import {
NtfyConfig,
HomeassistantConfig,
BarkConfig,
WebhookConfig,
} from './common/config';
import L from './common/logger';
import { NotificationReason } from './interfaces/notification-reason';
Expand Down Expand Up @@ -73,6 +75,8 @@ export async function sendNotification(
return new BarkNotifier(notifierConfig as BarkConfig);
case NotificationType.NTFY:
return new NtfyNotifier(notifierConfig as NtfyConfig);
case NotificationType.WEBHOOK:
return new WebhookNotifier(notifierConfig as WebhookConfig);
default:
throw new Error(`Unexpected notifier config: ${notifierConfig.type}`);
}
Expand Down

0 comments on commit 734c18d

Please sign in to comment.