2025-12-11 10:40:55 +01:00
|
|
|
/*
|
2026-01-12 15:00:36 +01:00
|
|
|
* Copyright (c) 2026 by Christian Kellner.
|
2025-12-11 10:40:55 +01:00
|
|
|
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
|
|
|
|
*/
|
|
|
|
|
|
2025-07-26 20:42:58 +02:00
|
|
|
import { getJobs } from '../storage/jobStorage.js';
|
|
|
|
|
import { getUniqueId } from './uniqueId.js';
|
2025-12-09 13:56:46 +01:00
|
|
|
import { getPackageVersion, inDevMode } from '../../utils.js';
|
2024-12-03 14:23:09 +01:00
|
|
|
import os from 'os';
|
2025-09-12 13:38:53 +02:00
|
|
|
import fetch from 'node-fetch';
|
2025-09-13 18:57:56 +02:00
|
|
|
import logger from '../logger.js';
|
2025-12-09 13:56:46 +01:00
|
|
|
import { getSettings } from '../storage/settingsStorage.js';
|
2024-11-22 09:11:10 +01:00
|
|
|
|
2025-09-12 13:38:53 +02:00
|
|
|
const deviceId = getUniqueId() || 'N/A';
|
2024-12-17 13:07:25 +01:00
|
|
|
const version = await getPackageVersion();
|
2025-09-12 13:38:53 +02:00
|
|
|
const FREDY_TRACKING_URL = 'https://fredy.orange-coding.net/tracking';
|
2026-06-14 11:00:58 +02:00
|
|
|
const TRACKING_CATEGORY = 'fredy';
|
2026-02-16 12:29:02 +01:00
|
|
|
const isDocker = process.env.IS_DOCKER != null;
|
2024-11-20 22:22:16 +01:00
|
|
|
|
2026-02-04 14:41:55 +01:00
|
|
|
const staticTrackingData = {
|
|
|
|
|
operatingSystem: os.platform(),
|
|
|
|
|
osVersion: os.release(),
|
2026-02-16 12:29:02 +01:00
|
|
|
isDocker,
|
2026-02-04 14:41:55 +01:00
|
|
|
arch: process.arch,
|
|
|
|
|
language: process.env.LANG || 'en',
|
|
|
|
|
nodeVersion: process.version || 'N/A',
|
|
|
|
|
deviceId,
|
|
|
|
|
version,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const shouldTrack = async () => {
|
|
|
|
|
const settings = await getSettings();
|
|
|
|
|
return settings.analyticsEnabled && !inDevMode();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const sendTrackingData = async (endpoint, payload) => {
|
2025-09-12 13:38:53 +02:00
|
|
|
try {
|
2026-02-04 14:41:55 +01:00
|
|
|
const response = await fetch(`${FREDY_TRACKING_URL}${endpoint}`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
body: payload ? JSON.stringify(payload) : undefined,
|
|
|
|
|
});
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
logger.warn(`Error sending tracking data to ${endpoint}. Status: ${response.status}`);
|
2024-11-20 22:22:16 +01:00
|
|
|
}
|
2025-09-12 13:38:53 +02:00
|
|
|
} catch (error) {
|
2026-02-04 14:41:55 +01:00
|
|
|
logger.warn(`Error sending tracking data to ${endpoint}`, error);
|
2025-07-26 20:42:58 +02:00
|
|
|
}
|
2024-11-22 09:11:10 +01:00
|
|
|
};
|
|
|
|
|
|
2026-02-04 14:41:55 +01:00
|
|
|
export const trackMainEvent = async () => {
|
|
|
|
|
if (!(await shouldTrack())) return;
|
|
|
|
|
|
|
|
|
|
const activeProvider = new Set();
|
|
|
|
|
const activeAdapter = new Set();
|
|
|
|
|
|
|
|
|
|
const jobs = getJobs();
|
|
|
|
|
|
|
|
|
|
if (jobs != null && jobs.length > 0) {
|
|
|
|
|
jobs.forEach((job) => {
|
|
|
|
|
job.provider.forEach((provider) => activeProvider.add(provider.id));
|
|
|
|
|
job.notificationAdapter.forEach((adapter) => activeAdapter.add(adapter.id));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const trackingObj = await enrichTrackingObject({
|
|
|
|
|
adapter: Array.from(activeAdapter),
|
|
|
|
|
provider: Array.from(activeProvider),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
await sendTrackingData('/main', trackingObj);
|
2026-01-22 16:09:36 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-17 12:35:39 +01:00
|
|
|
export const trackPoi = async (poi) => {
|
2026-02-04 14:41:55 +01:00
|
|
|
if (!(await shouldTrack())) return;
|
|
|
|
|
|
|
|
|
|
const trackingObj = await enrichTrackingObject({
|
2026-02-17 12:35:39 +01:00
|
|
|
feature: poi,
|
2026-02-04 14:41:55 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
await sendTrackingData('/feature', trackingObj);
|
|
|
|
|
};
|
|
|
|
|
|
2024-11-22 09:11:10 +01:00
|
|
|
/**
|
|
|
|
|
* Note, this will only be used when Fredy runs in demo mode
|
|
|
|
|
*/
|
2025-09-12 13:38:53 +02:00
|
|
|
export async function trackDemoAccessed() {
|
2025-12-09 13:56:46 +01:00
|
|
|
const settings = await getSettings();
|
|
|
|
|
if (settings.analyticsEnabled && !inDevMode() && settings.demoMode) {
|
2026-02-04 14:41:55 +01:00
|
|
|
const trackingObj = await enrichTrackingObject({});
|
|
|
|
|
await sendTrackingData('/demo/accessed', trackingObj);
|
2025-07-26 20:42:58 +02:00
|
|
|
}
|
2024-11-22 09:11:10 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-09 13:56:46 +01:00
|
|
|
async function enrichTrackingObject(trackingObject) {
|
|
|
|
|
const settings = await getSettings();
|
2024-11-22 09:11:10 +01:00
|
|
|
|
2025-07-26 20:42:58 +02:00
|
|
|
return {
|
2026-06-14 11:00:58 +02:00
|
|
|
category: TRACKING_CATEGORY,
|
2025-07-26 20:42:58 +02:00
|
|
|
...trackingObject,
|
2026-02-04 14:41:55 +01:00
|
|
|
...staticTrackingData,
|
2025-12-09 13:56:46 +01:00
|
|
|
isDemo: settings.demoMode,
|
2025-07-26 20:42:58 +02:00
|
|
|
};
|
2024-12-17 13:07:25 +01:00
|
|
|
}
|