179 lines
5.7 KiB
JavaScript
179 lines
5.7 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const CONFIG_DIR = path.join(__dirname, '..', 'config');
|
|
const SETTINGS_FILE = path.join(CONFIG_DIR, 'admin-settings.json');
|
|
|
|
const DEFAULT_SETTINGS = {
|
|
scheduleCron: '*/10 7-22 * * *',
|
|
randomDelayMinSeconds: 10,
|
|
randomDelayMaxSeconds: 120,
|
|
initialDelayMinSeconds: 5,
|
|
initialDelayMaxSeconds: 30,
|
|
storeWatchCron: '*/30 * * * *',
|
|
storeWatchInitialDelayMinSeconds: 10,
|
|
storeWatchInitialDelayMaxSeconds: 60,
|
|
storeWatchRequestDelayMs: 1000,
|
|
storePickupCheckDelayMs: 400,
|
|
ignoredSlots: [
|
|
{
|
|
storeId: '51450',
|
|
description: 'TVS'
|
|
}
|
|
],
|
|
notifications: {
|
|
ntfy: {
|
|
enabled: false,
|
|
serverUrl: 'https://ntfy.sh',
|
|
topicPrefix: '',
|
|
username: '',
|
|
password: ''
|
|
},
|
|
telegram: {
|
|
enabled: false,
|
|
botToken: ''
|
|
}
|
|
}
|
|
};
|
|
|
|
function ensureDir() {
|
|
if (!fs.existsSync(CONFIG_DIR)) {
|
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
}
|
|
}
|
|
|
|
function sanitizeNumber(value, fallback) {
|
|
const num = Number(value);
|
|
if (Number.isFinite(num) && num >= 0) {
|
|
return num;
|
|
}
|
|
return fallback;
|
|
}
|
|
|
|
function sanitizeIgnoredSlots(slots = []) {
|
|
if (!Array.isArray(slots)) {
|
|
return DEFAULT_SETTINGS.ignoredSlots;
|
|
}
|
|
return slots
|
|
.map((slot) => ({
|
|
storeId: slot?.storeId ? String(slot.storeId) : '',
|
|
description: slot?.description ? String(slot.description) : ''
|
|
}))
|
|
.filter((slot) => slot.storeId);
|
|
}
|
|
|
|
function sanitizeString(value) {
|
|
if (typeof value === 'string') {
|
|
return value.trim();
|
|
}
|
|
if (value === null || value === undefined) {
|
|
return '';
|
|
}
|
|
return String(value).trim();
|
|
}
|
|
|
|
function sanitizeNotifications(input = {}) {
|
|
const defaults = DEFAULT_SETTINGS.notifications;
|
|
return {
|
|
ntfy: {
|
|
enabled: !!(input?.ntfy?.enabled),
|
|
serverUrl: sanitizeString(input?.ntfy?.serverUrl || defaults.ntfy.serverUrl),
|
|
topicPrefix: sanitizeString(input?.ntfy?.topicPrefix || defaults.ntfy.topicPrefix),
|
|
username: sanitizeString(input?.ntfy?.username || defaults.ntfy.username),
|
|
password: sanitizeString(input?.ntfy?.password || defaults.ntfy.password)
|
|
},
|
|
telegram: {
|
|
enabled: !!(input?.telegram?.enabled),
|
|
botToken: sanitizeString(input?.telegram?.botToken || defaults.telegram.botToken)
|
|
}
|
|
};
|
|
}
|
|
|
|
function readSettings() {
|
|
ensureDir();
|
|
if (!fs.existsSync(SETTINGS_FILE)) {
|
|
fs.writeFileSync(SETTINGS_FILE, JSON.stringify(DEFAULT_SETTINGS, null, 2));
|
|
return { ...DEFAULT_SETTINGS };
|
|
}
|
|
|
|
try {
|
|
const raw = fs.readFileSync(SETTINGS_FILE, 'utf8');
|
|
const parsed = JSON.parse(raw);
|
|
return {
|
|
scheduleCron: parsed.scheduleCron || DEFAULT_SETTINGS.scheduleCron,
|
|
randomDelayMinSeconds: sanitizeNumber(parsed.randomDelayMinSeconds, DEFAULT_SETTINGS.randomDelayMinSeconds),
|
|
randomDelayMaxSeconds: sanitizeNumber(parsed.randomDelayMaxSeconds, DEFAULT_SETTINGS.randomDelayMaxSeconds),
|
|
initialDelayMinSeconds: sanitizeNumber(parsed.initialDelayMinSeconds, DEFAULT_SETTINGS.initialDelayMinSeconds),
|
|
initialDelayMaxSeconds: sanitizeNumber(parsed.initialDelayMaxSeconds, DEFAULT_SETTINGS.initialDelayMaxSeconds),
|
|
storeWatchCron: parsed.storeWatchCron || DEFAULT_SETTINGS.storeWatchCron,
|
|
storeWatchInitialDelayMinSeconds: sanitizeNumber(
|
|
parsed.storeWatchInitialDelayMinSeconds,
|
|
DEFAULT_SETTINGS.storeWatchInitialDelayMinSeconds
|
|
),
|
|
storeWatchInitialDelayMaxSeconds: sanitizeNumber(
|
|
parsed.storeWatchInitialDelayMaxSeconds,
|
|
DEFAULT_SETTINGS.storeWatchInitialDelayMaxSeconds
|
|
),
|
|
storeWatchRequestDelayMs: sanitizeNumber(
|
|
parsed.storeWatchRequestDelayMs,
|
|
DEFAULT_SETTINGS.storeWatchRequestDelayMs
|
|
),
|
|
storePickupCheckDelayMs: sanitizeNumber(
|
|
parsed.storePickupCheckDelayMs,
|
|
DEFAULT_SETTINGS.storePickupCheckDelayMs
|
|
),
|
|
ignoredSlots: sanitizeIgnoredSlots(parsed.ignoredSlots),
|
|
notifications: sanitizeNotifications(parsed.notifications)
|
|
};
|
|
} catch (error) {
|
|
console.error('Konnte Admin-Einstellungen nicht lesen:', error.message);
|
|
return { ...DEFAULT_SETTINGS };
|
|
}
|
|
}
|
|
|
|
function writeSettings(patch = {}) {
|
|
const current = readSettings();
|
|
const next = {
|
|
scheduleCron: patch.scheduleCron || current.scheduleCron,
|
|
randomDelayMinSeconds: sanitizeNumber(patch.randomDelayMinSeconds, current.randomDelayMinSeconds),
|
|
randomDelayMaxSeconds: sanitizeNumber(patch.randomDelayMaxSeconds, current.randomDelayMaxSeconds),
|
|
initialDelayMinSeconds: sanitizeNumber(patch.initialDelayMinSeconds, current.initialDelayMinSeconds),
|
|
initialDelayMaxSeconds: sanitizeNumber(patch.initialDelayMaxSeconds, current.initialDelayMaxSeconds),
|
|
storeWatchCron: patch.storeWatchCron || current.storeWatchCron,
|
|
storeWatchInitialDelayMinSeconds: sanitizeNumber(
|
|
patch.storeWatchInitialDelayMinSeconds,
|
|
current.storeWatchInitialDelayMinSeconds
|
|
),
|
|
storeWatchInitialDelayMaxSeconds: sanitizeNumber(
|
|
patch.storeWatchInitialDelayMaxSeconds,
|
|
current.storeWatchInitialDelayMaxSeconds
|
|
),
|
|
storeWatchRequestDelayMs: sanitizeNumber(
|
|
patch.storeWatchRequestDelayMs,
|
|
current.storeWatchRequestDelayMs
|
|
),
|
|
storePickupCheckDelayMs: sanitizeNumber(
|
|
patch.storePickupCheckDelayMs,
|
|
current.storePickupCheckDelayMs
|
|
),
|
|
ignoredSlots:
|
|
patch.ignoredSlots !== undefined
|
|
? sanitizeIgnoredSlots(patch.ignoredSlots)
|
|
: current.ignoredSlots,
|
|
notifications:
|
|
patch.notifications !== undefined
|
|
? sanitizeNotifications(patch.notifications)
|
|
: current.notifications
|
|
};
|
|
|
|
ensureDir();
|
|
fs.writeFileSync(SETTINGS_FILE, JSON.stringify(next, null, 2));
|
|
return next;
|
|
}
|
|
|
|
module.exports = {
|
|
DEFAULT_SETTINGS,
|
|
readSettings,
|
|
writeSettings
|
|
};
|