2026-01-22 16:09:36 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2026 by Christian Kellner.
|
|
|
|
|
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import restana from 'restana';
|
|
|
|
|
import SqliteConnection from '../../services/storage/SqliteConnection.js';
|
2026-01-28 15:55:23 +01:00
|
|
|
import { getSettings, upsertSettings } from '../../services/storage/settingsStorage.js';
|
|
|
|
|
import { resetGeocoordinatesAndDistanceForUser } from '../../services/storage/listingsStorage.js';
|
2026-01-22 16:09:36 +01:00
|
|
|
import { geocodeAddress } from '../../services/geocoding/geoCodingService.js';
|
|
|
|
|
import { autocompleteAddress } from '../../services/geocoding/autocompleteService.js';
|
|
|
|
|
import { fromJson } from '../../utils.js';
|
2026-02-17 12:35:39 +01:00
|
|
|
import { trackPoi } from '../../services/tracking/Tracker.js';
|
|
|
|
|
import { TRACKING_POIS } from '../../TRACKING_POIS.js';
|
2026-01-26 11:20:02 +01:00
|
|
|
import logger from '../../services/logger.js';
|
2026-01-28 15:55:23 +01:00
|
|
|
import { runGeoCordTask } from '../../services/crons/geocoding-cron.js';
|
2026-01-22 16:09:36 +01:00
|
|
|
|
|
|
|
|
const service = restana();
|
|
|
|
|
const userSettingsRouter = service.newRouter();
|
|
|
|
|
|
|
|
|
|
userSettingsRouter.get('/', async (req, res) => {
|
|
|
|
|
const userId = req.session.currentUser;
|
|
|
|
|
const rows = SqliteConnection.query('SELECT name, value FROM settings WHERE user_id = @userId', { userId });
|
|
|
|
|
const settings = {};
|
|
|
|
|
for (const r of rows) {
|
|
|
|
|
settings[r.name] = fromJson(r.value, null);
|
|
|
|
|
}
|
|
|
|
|
res.body = settings;
|
|
|
|
|
res.send();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
userSettingsRouter.get('/autocomplete', async (req, res) => {
|
|
|
|
|
const { q } = req.query;
|
|
|
|
|
try {
|
|
|
|
|
const results = await autocompleteAddress(q);
|
|
|
|
|
res.body = results;
|
|
|
|
|
res.send();
|
|
|
|
|
} catch (error) {
|
2026-01-26 11:20:02 +01:00
|
|
|
res.statusCode = 500;
|
|
|
|
|
res.send({ error: error.message });
|
2026-01-22 16:09:36 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-01-26 11:20:02 +01:00
|
|
|
userSettingsRouter.post('/home-address', async (req, res) => {
|
2026-01-22 16:09:36 +01:00
|
|
|
const userId = req.session.currentUser;
|
|
|
|
|
const { home_address } = req.body;
|
2026-01-28 15:55:23 +01:00
|
|
|
const settings = await getSettings();
|
|
|
|
|
|
|
|
|
|
if (settings.demoMode) {
|
|
|
|
|
res.send(new Error('In demo mode, it is not allowed to change the home address.'));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-01-22 16:09:36 +01:00
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (home_address) {
|
2026-02-17 12:35:39 +01:00
|
|
|
await trackPoi(TRACKING_POIS.DISTANCE_ADDRESS_ENTERED);
|
2026-01-22 16:09:36 +01:00
|
|
|
const coords = await geocodeAddress(home_address);
|
|
|
|
|
if (coords && coords.lat !== -1) {
|
|
|
|
|
upsertSettings({ home_address: { address: home_address, coords } }, userId);
|
2026-01-28 15:55:23 +01:00
|
|
|
resetGeocoordinatesAndDistanceForUser(userId);
|
|
|
|
|
//we do NOT wait for this to finish, as we don't want to block the response
|
|
|
|
|
runGeoCordTask();
|
2026-01-22 16:09:36 +01:00
|
|
|
res.send({ success: true, coords });
|
|
|
|
|
} else {
|
2026-01-26 11:20:02 +01:00
|
|
|
res.statusCode = 400;
|
|
|
|
|
res.send({ error: 'Could not geocode address' });
|
2026-01-22 16:09:36 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
upsertSettings({ home_address: null }, userId);
|
|
|
|
|
res.send({ success: true });
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
2026-01-26 11:20:02 +01:00
|
|
|
logger.error('Error updating home address settings', error);
|
|
|
|
|
res.statusCode = 500;
|
|
|
|
|
res.send({ error: error.message });
|
2026-01-22 16:09:36 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-02-17 12:35:39 +01:00
|
|
|
userSettingsRouter.post('/news-hash', async (req, res) => {
|
|
|
|
|
const userId = req.session.currentUser;
|
|
|
|
|
const { news_hash } = req.body;
|
|
|
|
|
|
|
|
|
|
const globalSettings = await getSettings();
|
|
|
|
|
if (globalSettings.demoMode) {
|
|
|
|
|
res.statusCode = 403;
|
|
|
|
|
res.send({ error: 'In demo mode, it is not allowed to change settings.' });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
upsertSettings({ news_hash }, userId);
|
|
|
|
|
res.send({ success: true });
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.error('Error updating news hash', error);
|
|
|
|
|
res.statusCode = 500;
|
|
|
|
|
res.send({ error: error.message });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-07 19:53:40 +02:00
|
|
|
userSettingsRouter.post('/provider-details', async (req, res) => {
|
2026-03-08 09:08:40 +01:00
|
|
|
const userId = req.session.currentUser;
|
2026-04-07 19:53:40 +02:00
|
|
|
const { provider_details } = req.body;
|
2026-03-08 09:08:40 +01:00
|
|
|
|
|
|
|
|
const globalSettings = await getSettings();
|
|
|
|
|
if (globalSettings.demoMode) {
|
|
|
|
|
res.statusCode = 403;
|
|
|
|
|
res.send({ error: 'In demo mode, it is not allowed to change settings.' });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-07 19:53:40 +02:00
|
|
|
if (!Array.isArray(provider_details)) {
|
|
|
|
|
res.statusCode = 400;
|
|
|
|
|
res.send({ error: 'provider_details must be an array of provider ids.' });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-08 09:08:40 +01:00
|
|
|
try {
|
2026-04-07 19:53:40 +02:00
|
|
|
upsertSettings({ provider_details }, userId);
|
2026-03-08 09:08:40 +01:00
|
|
|
res.send({ success: true });
|
|
|
|
|
} catch (error) {
|
2026-04-07 19:53:40 +02:00
|
|
|
logger.error('Error updating provider details setting', error);
|
2026-03-08 09:08:40 +01:00
|
|
|
res.statusCode = 500;
|
|
|
|
|
res.send({ error: error.message });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-01-22 16:09:36 +01:00
|
|
|
export { userSettingsRouter };
|