Skip to content

Commit a28703b

Browse files
committed
Adds Apprise notifications
1 parent a5f730b commit a28703b

14 files changed

Lines changed: 198 additions & 29 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
- Slack
3737
- Twitch
3838
- Support for notifications
39+
- Apprise
3940
- Discord
41+
- Email (SMTP)
4042
- Home Assistant
4143
- Pushover
4244
- Slack

app/constant/notifications.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
2+
"Apprise": {
3+
"id": "Apprise",
4+
"name": "Apprise",
5+
"icon": "apprise.svg"
6+
},
27
"Discord": {
38
"id": "Discord",
49
"name": "Discord",
@@ -34,4 +39,4 @@
3439
"name": "Webhook",
3540
"icon": "webhook.svg"
3641
}
37-
}
42+
}

app/constant/notifications/layout/apprise.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,20 @@ export const AppriseLayout: NotificationInputLayoutType[] = [
1515
type: 'password',
1616
isDataField: false,
1717
key: 'token',
18-
title: 'notification.input.webhook_url',
19-
placeholder: 'https://discord.com/api/webhooks',
20-
subtitle: {
21-
text: 'notification.discord.token_description',
22-
link: 'http://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks',
23-
},
18+
title: 'Apprise Webhook URL',
19+
placeholder: 'https://apprise.lunalytics.xyz/notify',
2420
},
2521
{
2622
type: 'input',
2723
isDataField: true,
28-
key: 'username',
29-
title: 'notification.input.webhook_username',
30-
placeholder: 'Lunalytics',
31-
},
32-
{
33-
type: 'input',
34-
isDataField: true,
35-
key: 'textMessage',
36-
title: 'notification.input.text_message',
37-
placeholder: 'Alert @everyone',
24+
key: 'urls',
25+
title: 'Notification URL(s)',
26+
placeholder:
27+
'discord://webhook_id/webhook_token, pushover://user_key/app_token',
28+
subtitle: {
29+
text: 'Seperate multiple URLs with commas to send to multiple services. For more information, see the Apprise documentation: ',
30+
link: 'https://github.com/caronc/apprise-api',
31+
},
3832
},
3933
],
4034
},

app/constant/notifications/layout/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export { AppriseLayout as Apprise } from './apprise';
12
export { DiscordLayout as Discord } from './discord';
23
export { EmailLayout as Email } from './email';
34
export { HomeAssistantLayout as HomeAssistant } from './homeAssistant';

package-lock.json

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lunalytics",
3-
"version": "0.10.9",
3+
"version": "0.10.10",
44
"description": "Open source Node.js server/website monitoring tool",
55
"private": true,
66
"author": "KSJaay <ksjaay@gmail.com>",

public/notifications/apprise.svg

Lines changed: 1 addition & 0 deletions
Loading

scripts/notification.js

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ const appriseDirs = [
3232
extension: '.ts',
3333
},
3434
{
35-
directory: path.resolve(process.cwd(), 'shared', 'validators'),
35+
directory: path.resolve(
36+
process.cwd(),
37+
'shared',
38+
'validators',
39+
'notifications'
40+
),
3641
extension: '.js',
3742
},
3843
];
@@ -41,7 +46,7 @@ appriseDirs.forEach(({ directory, extension }) => {
4146
if (!fs.existsSync(directory)) {
4247
fs.mkdirSync(directory, { recursive: true });
4348
}
44-
const filePath = path.join(directory, fileName + extension);
49+
const filePath = path.join(directory, fileName.toLowerCase() + extension);
4550
try {
4651
fs.writeFileSync(filePath, '', { flag: 'wx' });
4752
logger.info(`File created: ${filePath}`);
@@ -53,3 +58,42 @@ appriseDirs.forEach(({ directory, extension }) => {
5358
}
5459
}
5560
});
61+
62+
const notificationJson = path.resolve(
63+
process.cwd(),
64+
'app',
65+
'constant',
66+
'notifications.json'
67+
);
68+
69+
const data = fs.readFileSync(notificationJson, 'utf-8');
70+
const notifications = JSON.parse(data);
71+
72+
const notificationName =
73+
fileName.charAt(0).toUpperCase() + fileName.slice(1).toLowerCase();
74+
75+
if (!notifications[notificationName]) {
76+
notifications[notificationName] = {
77+
id: notificationName,
78+
name: notificationName,
79+
icon: `${notificationName.toLowerCase()}.svg`,
80+
};
81+
82+
fs.writeFileSync(
83+
notificationJson,
84+
JSON.stringify(
85+
Object.keys(notifications)
86+
.sort()
87+
.reduce((obj, key) => {
88+
obj[key] = notifications[key];
89+
return obj;
90+
}, {}),
91+
null,
92+
2
93+
),
94+
'utf-8'
95+
);
96+
logger.info(
97+
`Notification entry added for ${notificationName} in notifications.json. Please add ${notificationName.toLowerCase()}.svg`
98+
);
99+
}

server/notifications/apprise.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import axios from 'axios';
2+
import NotificationBase from './base.js';
3+
import NotificationReplacers from '../../shared/notifications/replacers/notification.js';
4+
import { AppriseTemplateMessages } from '../../shared/notifications/apprise.js';
5+
6+
class Apprise extends NotificationBase {
7+
name = 'Apprise';
8+
9+
async send(notification, monitor, heartbeat) {
10+
try {
11+
const template =
12+
AppriseTemplateMessages[notification.messageType] ||
13+
notification.payload;
14+
15+
const content = NotificationReplacers(template, monitor, heartbeat);
16+
17+
await axios.post(notification.token, {
18+
...content,
19+
urls: notification.data.urls.split(',').map((url) => url.trim()),
20+
});
21+
return this.success;
22+
} catch (error) {
23+
this.handleError(error);
24+
}
25+
}
26+
27+
async test(notification) {
28+
try {
29+
await axios.post(notification.token, {
30+
title: 'This is a test message',
31+
urls: notification.data.urls.split(',').map((url) => url.trim()),
32+
});
33+
return this.success;
34+
} catch (error) {
35+
this.handleError(error);
36+
}
37+
}
38+
39+
async sendRecovery(notification, monitor, heartbeat) {
40+
try {
41+
const template = AppriseTemplateMessages.recovery;
42+
43+
const content = NotificationReplacers(template, monitor, heartbeat);
44+
45+
await axios.post(notification.token, {
46+
...content,
47+
urls: notification.data.urls.split(',').map((url) => url.trim()),
48+
});
49+
return this.success;
50+
} catch (error) {
51+
this.handleError(error);
52+
}
53+
}
54+
}
55+
56+
export default Apprise;

server/notifications/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Apprise from './apprise.js';
12
import Discord from './discord.js';
23
import Email from './email.js';
34
import HomeAssistant from './homeAssistant.js';
@@ -7,6 +8,7 @@ import Slack from './slack.js';
78
import Webhook from './webhook.js';
89

910
const NotificationServices = {
11+
Apprise,
1012
Discord,
1113
Email,
1214
HomeAssistant,

0 commit comments

Comments
 (0)