Files
sloth-manager/backend/src/notify.js
T
2026-06-16 21:37:11 +02:00

163 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const settings = require('./settings');
const db = require('./db');
const nodemailer = require('nodemailer');
// ─── Channel senders ──────────────────────────────────────────────────────────
async function sendGotify(title, message) {
const { gotify } = settings.get();
if (!gotify.enabled || !gotify.url || !gotify.token) return;
const base = gotify.url.replace(/\/$/, '');
try {
const res = await fetch(`${base}/message?token=${encodeURIComponent(gotify.token)}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, message, priority: gotify.priority ?? 5 }),
});
if (!res.ok) console.error(`[notify] Gotify error ${res.status}: ${await res.text().catch(() => '')}`);
} catch (err) {
console.error('[notify] Gotify failed:', err.message);
}
}
async function sendNtfy(title, message) {
const { ntfy } = settings.get();
if (!ntfy.enabled || !ntfy.url || !ntfy.topic) return;
const base = ntfy.url.replace(/\/$/, '');
const headers = {
'Content-Type': 'text/plain',
'Title': title,
'Priority': String(ntfy.priority ?? 3),
};
if (ntfy.token) headers['Authorization'] = `Bearer ${ntfy.token}`;
try {
const res = await fetch(`${base}/${encodeURIComponent(ntfy.topic)}`, {
method: 'POST',
headers,
body: message,
});
if (!res.ok) console.error(`[notify] ntfy error ${res.status}: ${await res.text().catch(() => '')}`);
} catch (err) {
console.error('[notify] ntfy failed:', err.message);
}
}
async function sendSmtp(title, message) {
const { smtp } = settings.get();
if (!smtp.enabled || !smtp.host || !smtp.to || !smtp.from) return;
try {
const transporter = nodemailer.createTransport({
host: smtp.host,
port: Number(smtp.port) || 587,
secure: smtp.secure === true || smtp.secure === 'true',
auth: smtp.username ? { user: smtp.username, pass: smtp.password } : undefined,
});
await transporter.sendMail({
from: smtp.from,
to: smtp.to,
subject: title,
text: message,
});
} catch (err) {
console.error('[notify] SMTP failed:', err.message);
}
}
async function sendWebhook(title, message) {
const { webhook } = settings.get();
if (!webhook.enabled || !webhook.url) return;
const body = JSON.stringify({ content: `**${title}**\n${message}` });
const headers = { 'Content-Type': 'application/json' };
if (webhook.secret) headers['X-Webhook-Secret'] = webhook.secret;
try {
const res = await fetch(webhook.url, { method: 'POST', headers, body });
if (!res.ok) console.error(`[notify] Webhook error ${res.status}: ${await res.text().catch(() => '')}`);
} catch (err) {
console.error('[notify] Webhook failed:', err.message);
}
}
// ─── Broadcast to all enabled channels ───────────────────────────────────────
async function notify(title, message) {
await Promise.all([
sendGotify(title, message),
sendNtfy(title, message),
sendSmtp(title, message),
sendWebhook(title, message),
]);
}
// ─── Exported senders for test routes ────────────────────────────────────────
async function testGotify(cfg) {
const base = cfg.url.replace(/\/$/, '');
const res = await fetch(`${base}/message?token=${encodeURIComponent(cfg.token)}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: '🦥 Sloth Manager — Test', message: 'Gotify notifications are working correctly.', priority: cfg.priority ?? 5 }),
});
if (!res.ok) throw new Error(`Gotify returned ${res.status}: ${await res.text().catch(() => '')}`);
}
async function testNtfy(cfg) {
const base = cfg.url.replace(/\/$/, '');
const headers = { 'Content-Type': 'text/plain', Title: '🦥 Sloth Manager — Test', Priority: String(cfg.priority ?? 3) };
if (cfg.token) headers['Authorization'] = `Bearer ${cfg.token}`;
const res = await fetch(`${base}/${encodeURIComponent(cfg.topic)}`, { method: 'POST', headers, body: 'ntfy notifications are working correctly.' });
if (!res.ok) throw new Error(`ntfy returned ${res.status}: ${await res.text().catch(() => '')}`);
}
async function testSmtp(cfg) {
const transporter = nodemailer.createTransport({
host: cfg.host,
port: Number(cfg.port) || 587,
secure: cfg.secure === true || cfg.secure === 'true',
auth: cfg.username ? { user: cfg.username, pass: cfg.password } : undefined,
});
await transporter.verify();
await transporter.sendMail({
from: cfg.from,
to: cfg.to,
subject: '🦥 Sloth Manager — Test',
text: 'SMTP notifications are working correctly.',
});
}
async function testWebhook(cfg) {
const headers = { 'Content-Type': 'application/json' };
if (cfg.secret) headers['X-Webhook-Secret'] = cfg.secret;
const res = await fetch(cfg.url, {
method: 'POST',
headers,
body: JSON.stringify({ content: '**🦥 Sloth Manager — Test**\nWebhook notifications are working correctly.' }),
});
if (!res.ok) throw new Error(`Webhook returned ${res.status}: ${await res.text().catch(() => '')}`);
}
// ─── Event helpers ────────────────────────────────────────────────────────────
function eventEnabled(key) {
return settings.get().notifications?.[key] !== false;
}
function recordAdded(provider, zoneId, record) {
if (!eventEnabled('dns_add')) return;
const zoneName = db.getZoneName(provider, zoneId);
return notify(`DNS Record Added`, `[${provider}] ${zoneName}\n+ ${record.type} ${record.name}${record.content}`);
}
function recordUpdated(provider, zoneId, oldRecord, newRecord) {
if (!eventEnabled('dns_update')) return;
const zoneName = db.getZoneName(provider, zoneId);
return notify(`DNS Record Updated`, `[${provider}] ${zoneName}\n✎ ${oldRecord.type} ${oldRecord.name}\n ${oldRecord.content}${newRecord.content}`);
}
function recordDeleted(provider, zoneId, record) {
if (!eventEnabled('dns_delete')) return;
const zoneName = db.getZoneName(provider, zoneId);
return notify(`DNS Record Deleted`, `[${provider}] ${zoneName}\n ${record.type} ${record.name} ${record.content}`);
}
module.exports = { notify, testGotify, testNtfy, testSmtp, testWebhook, recordAdded, recordUpdated, recordDeleted };