55 lines
1.6 KiB
JavaScript
55 lines
1.6 KiB
JavaScript
'use strict';
|
|
|
|
const { get } = require('../services/stats');
|
|
|
|
// Whitelist estricta: solo claves conocidas salen en la respuesta
|
|
const PROVIDER_LABELS = {
|
|
instagram: 'Instagram',
|
|
facebook: 'Facebook',
|
|
twitter_x: 'X (Twitter)',
|
|
linkedin: 'LinkedIn',
|
|
tiktok: 'TikTok',
|
|
snapchat: 'Snapchat',
|
|
microsoft: 'Microsoft',
|
|
apple: 'Apple',
|
|
google: 'Google',
|
|
amazon: 'Amazon',
|
|
reddit: 'Reddit',
|
|
discord: 'Discord',
|
|
};
|
|
|
|
const VALID_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
|
|
function safeInt(v) {
|
|
const n = Math.floor(Number(v));
|
|
return Number.isFinite(n) && n >= 0 ? n : 0;
|
|
}
|
|
|
|
module.exports = (req, res) => {
|
|
const raw = get();
|
|
|
|
// Solo proveedores de la whitelist — cualquier clave extraña en stats.json se descarta
|
|
const providers = Object.entries(raw.by_provider || {})
|
|
.filter(([key]) => Object.prototype.hasOwnProperty.call(PROVIDER_LABELS, key))
|
|
.map(([key, v]) => ({
|
|
name: PROVIDER_LABELS[key], // nombre viene de whitelist, no del fichero
|
|
icon_key: key, // clave corta para iconos en cliente (solo a-z_)
|
|
sent: safeInt(v.sent),
|
|
redirected: safeInt(v.redirected),
|
|
total: safeInt(v.sent) + safeInt(v.redirected),
|
|
}))
|
|
.sort((a, b) => b.total - a.total);
|
|
|
|
// updated: solo si es una fecha válida YYYY-MM-DD, si no null
|
|
const updated = typeof raw.updated === 'string' && VALID_DATE.test(raw.updated)
|
|
? raw.updated
|
|
: null;
|
|
|
|
res.json({
|
|
total_sent: safeInt(raw.total_sent),
|
|
total_redirected: safeInt(raw.total_redirected),
|
|
total_searches: safeInt(raw.total_searches),
|
|
providers,
|
|
updated,
|
|
});
|
|
};
|