feat: add ntfy and telegram notification workflows
This commit is contained in:
128
services/notificationService.js
Normal file
128
services/notificationService.js
Normal file
@@ -0,0 +1,128 @@
|
||||
const axios = require('axios');
|
||||
const adminConfig = require('./adminConfig');
|
||||
const { readNotificationSettings } = require('./userSettingsStore');
|
||||
|
||||
function formatDateLabel(dateInput) {
|
||||
try {
|
||||
const date = new Date(dateInput);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return 'unbekanntes Datum';
|
||||
}
|
||||
return date.toLocaleString('de-DE', {
|
||||
weekday: 'short',
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
} catch (_error) {
|
||||
return 'unbekanntes Datum';
|
||||
}
|
||||
}
|
||||
|
||||
async function sendNtfyNotification(adminNtfy, userNtfy, payload) {
|
||||
if (!adminNtfy?.enabled || !userNtfy?.enabled || !userNtfy.topic) {
|
||||
return;
|
||||
}
|
||||
const server = (userNtfy.serverUrl || adminNtfy.serverUrl || 'https://ntfy.sh').replace(/\/+$/, '');
|
||||
const topicPrefix = adminNtfy.topicPrefix ? `${adminNtfy.topicPrefix.replace(/\/+$/, '')}/` : '';
|
||||
const topic = `${topicPrefix}${userNtfy.topic.replace(/^\//, '')}`;
|
||||
const url = `${server}/${topic}`;
|
||||
const headers = {
|
||||
Title: payload.title,
|
||||
Priority: payload.priority || 'default'
|
||||
};
|
||||
if (adminNtfy.username && adminNtfy.password) {
|
||||
const credentials = Buffer.from(`${adminNtfy.username}:${adminNtfy.password}`).toString('base64');
|
||||
headers.Authorization = `Basic ${credentials}`;
|
||||
}
|
||||
await axios.post(url, payload.message, { headers, timeout: 15000 });
|
||||
}
|
||||
|
||||
async function sendTelegramNotification(adminTelegram, userTelegram, payload) {
|
||||
if (!adminTelegram?.enabled || !adminTelegram.botToken || !userTelegram?.enabled || !userTelegram.chatId) {
|
||||
return;
|
||||
}
|
||||
const endpoint = `https://api.telegram.org/bot${adminTelegram.botToken}/sendMessage`;
|
||||
await axios.post(
|
||||
endpoint,
|
||||
{
|
||||
chat_id: userTelegram.chatId,
|
||||
text: `${payload.title}\n${payload.message}`,
|
||||
disable_web_page_preview: true
|
||||
},
|
||||
{ timeout: 15000 }
|
||||
);
|
||||
}
|
||||
|
||||
async function notifyChannels(profileId, template) {
|
||||
const adminSettings = adminConfig.readSettings();
|
||||
const userSettings = readNotificationSettings(profileId);
|
||||
try {
|
||||
await Promise.allSettled([
|
||||
sendNtfyNotification(adminSettings.notifications?.ntfy, userSettings.notifications?.ntfy, template),
|
||||
sendTelegramNotification(adminSettings.notifications?.telegram, userSettings.notifications?.telegram, template)
|
||||
]);
|
||||
} catch (error) {
|
||||
console.error('[NOTIFICATIONS] Versand fehlgeschlagen:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function sendSlotNotification({ profileId, storeName, pickupDate, onlyNotify, booked }) {
|
||||
const dateLabel = formatDateLabel(pickupDate);
|
||||
const title = onlyNotify
|
||||
? `Slot verfügbar bei ${storeName}`
|
||||
: booked
|
||||
? `Slot gebucht bei ${storeName}`
|
||||
: `Slot gefunden bei ${storeName}`;
|
||||
const message = onlyNotify
|
||||
? `Es wurde ein freier Slot am ${dateLabel} entdeckt.`
|
||||
: booked
|
||||
? `Der Slot am ${dateLabel} wurde erfolgreich gebucht.`
|
||||
: `Es wurde ein Slot am ${dateLabel} gefunden.`;
|
||||
|
||||
await notifyChannels(profileId, {
|
||||
title,
|
||||
message,
|
||||
priority: booked ? 'high' : 'default'
|
||||
});
|
||||
}
|
||||
|
||||
async function sendTestNotification(profileId, channel) {
|
||||
const title = 'Pickup Benachrichtigung (Test)';
|
||||
const message = 'Das ist eine Testnachricht. Bei Fragen wende dich bitte an den Admin.';
|
||||
const adminSettings = adminConfig.readSettings();
|
||||
const userSettings = readNotificationSettings(profileId);
|
||||
const tasks = [];
|
||||
|
||||
if (!channel || channel === 'ntfy') {
|
||||
tasks.push(
|
||||
sendNtfyNotification(adminSettings.notifications?.ntfy, userSettings.notifications?.ntfy, {
|
||||
title,
|
||||
message,
|
||||
priority: 'default'
|
||||
})
|
||||
);
|
||||
}
|
||||
if (!channel || channel === 'telegram') {
|
||||
tasks.push(
|
||||
sendTelegramNotification(adminSettings.notifications?.telegram, userSettings.notifications?.telegram, {
|
||||
title,
|
||||
message,
|
||||
priority: 'default'
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (tasks.length === 0) {
|
||||
throw new Error('Kein unterstützter Kanal oder Kanal deaktiviert.');
|
||||
}
|
||||
|
||||
await Promise.all(tasks);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
sendSlotNotification,
|
||||
sendTestNotification
|
||||
};
|
||||
Reference in New Issue
Block a user