135 lines
3.5 KiB
JavaScript
135 lines
3.5 KiB
JavaScript
const { getDb } = require('../db/database');
|
|
const logger = require('./logger').child('USER_PRESET_DEFAULTS');
|
|
|
|
const SLOT_KEYS = Object.freeze([
|
|
'bluray_movie',
|
|
'bluray_series',
|
|
'dvd_movie',
|
|
'dvd_series'
|
|
]);
|
|
const SLOT_KEY_SET = new Set(SLOT_KEYS);
|
|
const SLOT_ALLOWED_MEDIA_TYPES = Object.freeze({
|
|
bluray_movie: new Set(['bluray', 'all']),
|
|
bluray_series: new Set(['bluray', 'all']),
|
|
dvd_movie: new Set(['dvd', 'all']),
|
|
dvd_series: new Set(['dvd', 'all'])
|
|
});
|
|
|
|
function normalizePresetId(value) {
|
|
if (value === null || value === undefined) {
|
|
return null;
|
|
}
|
|
if (typeof value === 'string' && value.trim() === '') {
|
|
return null;
|
|
}
|
|
const numeric = Number(value);
|
|
if (!Number.isFinite(numeric) || numeric <= 0) {
|
|
return null;
|
|
}
|
|
return Math.trunc(numeric);
|
|
}
|
|
|
|
function buildDefaultsMap(rows = []) {
|
|
const map = Object.fromEntries(SLOT_KEYS.map((key) => [key, null]));
|
|
for (const row of rows) {
|
|
const slotKey = String(row?.slot_key || '').trim();
|
|
if (!SLOT_KEY_SET.has(slotKey)) {
|
|
continue;
|
|
}
|
|
const presetId = normalizePresetId(row?.preset_id);
|
|
map[slotKey] = presetId;
|
|
}
|
|
return map;
|
|
}
|
|
|
|
async function listDefaults() {
|
|
const db = await getDb();
|
|
const rows = await db.all(
|
|
`
|
|
SELECT slot_key, preset_id
|
|
FROM user_preset_defaults
|
|
WHERE slot_key IN (${SLOT_KEYS.map(() => '?').join(', ')})
|
|
ORDER BY slot_key ASC
|
|
`,
|
|
SLOT_KEYS
|
|
);
|
|
return buildDefaultsMap(rows);
|
|
}
|
|
|
|
async function updateDefaults(payload = {}) {
|
|
const defaults = payload && typeof payload === 'object'
|
|
? (payload.defaults && typeof payload.defaults === 'object' ? payload.defaults : payload)
|
|
: {};
|
|
const updates = [];
|
|
|
|
for (const [slotKey, rawPresetId] of Object.entries(defaults)) {
|
|
if (!SLOT_KEY_SET.has(slotKey)) {
|
|
const error = new Error(`Ungültiger Slot: ${slotKey}`);
|
|
error.statusCode = 400;
|
|
throw error;
|
|
}
|
|
updates.push({ slotKey, presetId: normalizePresetId(rawPresetId) });
|
|
}
|
|
|
|
if (updates.length === 0) {
|
|
return listDefaults();
|
|
}
|
|
|
|
const db = await getDb();
|
|
for (const update of updates) {
|
|
if (update.presetId === null) {
|
|
continue;
|
|
}
|
|
const exists = await db.get(
|
|
`SELECT id, media_type FROM user_presets WHERE id = ? LIMIT 1`,
|
|
[update.presetId]
|
|
);
|
|
if (!exists) {
|
|
const error = new Error(`Preset ${update.presetId} nicht gefunden.`);
|
|
error.statusCode = 404;
|
|
throw error;
|
|
}
|
|
const mediaType = String(exists.media_type || '').trim().toLowerCase();
|
|
const allowedMediaTypes = SLOT_ALLOWED_MEDIA_TYPES[update.slotKey] || new Set(['all']);
|
|
if (!allowedMediaTypes.has(mediaType)) {
|
|
const error = new Error(
|
|
`Preset ${update.presetId} (${mediaType || 'unbekannt'}) ist für ${update.slotKey} nicht zulässig.`
|
|
);
|
|
error.statusCode = 400;
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
await db.exec('BEGIN');
|
|
try {
|
|
for (const update of updates) {
|
|
await db.run(
|
|
`
|
|
INSERT INTO user_preset_defaults (slot_key, preset_id)
|
|
VALUES (?, ?)
|
|
ON CONFLICT(slot_key) DO UPDATE SET preset_id = excluded.preset_id
|
|
`,
|
|
[update.slotKey, update.presetId]
|
|
);
|
|
}
|
|
await db.exec('COMMIT');
|
|
} catch (error) {
|
|
await db.exec('ROLLBACK');
|
|
throw error;
|
|
}
|
|
|
|
logger.info('update', {
|
|
updates: updates.map((entry) => ({
|
|
slotKey: entry.slotKey,
|
|
presetId: entry.presetId
|
|
}))
|
|
});
|
|
return listDefaults();
|
|
}
|
|
|
|
module.exports = {
|
|
SLOT_KEYS,
|
|
listDefaults,
|
|
updateDefaults
|
|
};
|