131 lines
4.1 KiB
JavaScript
131 lines
4.1 KiB
JavaScript
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 sanitizedPrefix = (adminNtfy.topicPrefix || '').replace(/^-+|-+$/g, '');
|
|
const sanitizedTopic = (userNtfy.topic || '').replace(/^-+|-+$/g, '');
|
|
const separator = sanitizedPrefix && sanitizedTopic ? '-' : '';
|
|
const topic = `${sanitizedPrefix}${separator}${sanitizedTopic}` || sanitizedPrefix || sanitizedTopic;
|
|
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
|
|
};
|