- Aggiunto le Statistiche di visualizzazione delle pagine.
- Aggiunto il componente per visualizzare le statistiche
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
DATABASE=test_FreePlanet
|
||||
DATABASE=test_PiuCheBuono
|
||||
UDB=paofreeplanet
|
||||
PDB=mypassword@1A
|
||||
SEND_EMAIL=0
|
||||
SEND_EMAIL_ORDERS=1
|
||||
PORT=3000
|
||||
appTelegram_TEST=["1","13"]
|
||||
appTelegram=["1","13"]
|
||||
appTelegram_DEVELOP=["13"]
|
||||
appTelegram_TEST=["1","17"]
|
||||
appTelegram=["1","17"]
|
||||
appTelegram_DEVELOP=["17"]
|
||||
DOMAIN=mongodb://localhost:27017/
|
||||
AUTH_MONGODB=0
|
||||
ENABLE_PUSHNOTIFICATION=1
|
||||
@@ -29,7 +29,7 @@ GCM_API_KEY=""
|
||||
PROD=0
|
||||
PROJECT_DESCR_MAIN='__PROJECTS'
|
||||
SECRK=Askb38v23jjDFaoskBOWj92axXCQ
|
||||
TOKEN_LIFE=1m
|
||||
TOKEN_LIFE=2h
|
||||
REFRESH_TOKEN_LIFE=14d
|
||||
FTPSERVER_HOST=139.162.166.31
|
||||
FTPSERVER_PORT=21
|
||||
@@ -38,4 +38,9 @@ FTPSERVER_PWD=ftpmypwd@1A_
|
||||
AUTH_NEW_SITES=123123123
|
||||
SCRIPTS_DIR=admin_scripts
|
||||
CLOUDFLARE_TOKENS=[{"label":"Paolo.arena77@gmail.com","value":"M9EM309v8WFquJKpYgZCw-TViM2wX6vB3wlK6GD0"},{"label":"gruppomacro.com","value":"bqmzGShoX7WqOBzkXocoECyBkPq3GfqcM5t6VFd8"}]
|
||||
MIAB_HOST=box.lamiaposta.org
|
||||
MIAB_ADMIN_EMAIL=admin@lamiaposta.org
|
||||
MIAB_ADMIN_PASSWORD=passpao1pabox@1A
|
||||
DS_API_KEY="sk-222e3addb3d8455d8b0516d93906eec7"
|
||||
SERVER_A_URL="http://51.77.156.69:3000"
|
||||
API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK"
|
||||
26
src/server/models/PageView.js
Executable file
26
src/server/models/PageView.js
Executable file
@@ -0,0 +1,26 @@
|
||||
// /backend/models/PageView.js
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const PageViewSchema = new mongoose.Schema({
|
||||
url: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
idapp: String,
|
||||
ip: {
|
||||
type: String,
|
||||
default: 'unknown'
|
||||
},
|
||||
userId: String,
|
||||
username: String,
|
||||
userAgent: {
|
||||
type: String
|
||||
},
|
||||
timestamp: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('PageView', PageViewSchema);
|
||||
@@ -1,7 +1,8 @@
|
||||
const express = require("express");
|
||||
const { authenticate } = require("../middleware/authenticate");
|
||||
const express = require('express');
|
||||
const { authenticate, authenticate_noerror } = require('../middleware/authenticate');
|
||||
|
||||
const router = express.Router();
|
||||
const PageView = require('../models/PageView');
|
||||
|
||||
router.post('/test-lungo', authenticate, (req, res) => {
|
||||
const timeout = req.body.timeout;
|
||||
@@ -18,10 +19,241 @@ router.post('/test-lungo', authenticate, (req, res) => {
|
||||
// Verifico se la richiesta va a buon fine
|
||||
setTimeout(() => {
|
||||
if (!res.headersSent) {
|
||||
res.status(500).json({ ok: false, message: '❌ Errore durante l\'elaborazione della richiesta!' });
|
||||
res.status(500).json({ ok: false, message: "❌ Errore durante l'elaborazione della richiesta!" });
|
||||
}
|
||||
}, durataMs + 1000);
|
||||
});
|
||||
|
||||
router.post('/track-pageview', authenticate_noerror, async (req, res) => {
|
||||
const { url, userAgent, idapp } = req.body;
|
||||
const ip = req.ip || req.headers['x-forwarded-for'] || 'unknown';
|
||||
|
||||
try {
|
||||
const pageView = new PageView({
|
||||
url,
|
||||
ip,
|
||||
idapp,
|
||||
userId: req.user ? req.user._id : '',
|
||||
username: req.user ? req.user.username : '',
|
||||
userAgent,
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
await pageView.save();
|
||||
|
||||
res.status(200).json({ message: 'Visita registrata' });
|
||||
} catch (error) {
|
||||
console.error('Errore nel salvataggio della visita:', error);
|
||||
res.status(500).json({ error: 'Impossibile registrare la visita' });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/pageviews/stats', authenticate_noerror, async (req, res) => {
|
||||
const { userId, idapp, unique } = req.query;
|
||||
|
||||
try {
|
||||
const matchStage = { idapp };
|
||||
if (userId) {
|
||||
matchStage.$or = [{ userId }, { username: userId }];
|
||||
}
|
||||
|
||||
// Definiamo la base della pipeline
|
||||
const basePipeline = [{ $match: matchStage }];
|
||||
|
||||
// Pipeline per statistiche temporali (oggi, settimana, mese)
|
||||
const timeStatsPipeline = [
|
||||
...basePipeline,
|
||||
{
|
||||
$facet: {
|
||||
total: [{ $count: 'total' }],
|
||||
today: [{ $match: { timestamp: { $gte: startOfDay(new Date()) } } }, { $count: 'count' }],
|
||||
week: [{ $match: { timestamp: { $gte: startOfDay(subDays(new Date(), 7)) } } }, { $count: 'count' }],
|
||||
month: [{ $match: { timestamp: { $gte: startOfDay(subDays(new Date(), 30)) } } }, { $count: 'count' }],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// Eseguiamo solo la parte delle statistiche temporali
|
||||
const timeStatsResult = await PageView.aggregate(timeStatsPipeline);
|
||||
|
||||
// Ora costruiamo la pipeline completa per topPages (con o senza unique)
|
||||
let topPagesPipeline = [...basePipeline];
|
||||
|
||||
if (unique) {
|
||||
topPagesPipeline = [
|
||||
...topPagesPipeline,
|
||||
{
|
||||
$group: {
|
||||
_id: {
|
||||
url: '$url',
|
||||
userId: { $ifNull: ['$userId', '$ip'] },
|
||||
date: {
|
||||
$dateToString: {
|
||||
format: '%Y-%m-%d',
|
||||
date: '$timestamp',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{ $replaceRoot: { newRoot: '$_id' } },
|
||||
];
|
||||
}
|
||||
|
||||
// Aggiungi il group finale per contare le pagine
|
||||
const topPagesResult = await PageView.aggregate([
|
||||
...topPagesPipeline,
|
||||
{
|
||||
$group: {
|
||||
_id: '$url',
|
||||
count: { $sum: 1 },
|
||||
},
|
||||
},
|
||||
{ $sort: { count: -1 } },
|
||||
{ $limit: 10 },
|
||||
]);
|
||||
|
||||
// Formattazione dei risultati
|
||||
const formatCount = (arr) => (arr && arr.length > 0 ? arr[0].count || 0 : 0);
|
||||
|
||||
const stats = {
|
||||
total: formatCount(timeStatsResult[0]?.total),
|
||||
today: formatCount(timeStatsResult[0]?.today),
|
||||
week: formatCount(timeStatsResult[0]?.week),
|
||||
month: formatCount(timeStatsResult[0]?.month),
|
||||
topPages: topPagesResult,
|
||||
};
|
||||
|
||||
res.json(stats);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Errore nel calcolo delle statistiche' });
|
||||
}
|
||||
});
|
||||
|
||||
function startOfDay(date) {
|
||||
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
||||
}
|
||||
|
||||
function subDays(date, days) {
|
||||
const newDate = new Date(date);
|
||||
newDate.setDate(newDate.getDate() - days);
|
||||
return newDate;
|
||||
}
|
||||
|
||||
router.get('/pageviews/users', authenticate_noerror, async (req, res) => {
|
||||
try {
|
||||
const { idapp } = req.query;
|
||||
|
||||
// Trova tutte le entry con idapp e prendi userId e username
|
||||
const usersData = await PageView.find({ idapp }, { userId: 1, username: 1, _id: 0 }).lean();
|
||||
|
||||
// Usa un Map per garantire unicità basata su userId
|
||||
const uniqueUsersMap = new Map();
|
||||
|
||||
usersData.forEach(({ userId, username }) => {
|
||||
if (userId && !uniqueUsersMap.has(userId)) {
|
||||
uniqueUsersMap.set(userId, { userId, username });
|
||||
}
|
||||
});
|
||||
|
||||
// Converte la Map in array
|
||||
const uniqueUsers = Array.from(uniqueUsersMap.values());
|
||||
|
||||
res.json(uniqueUsers);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Errore nel recupero degli utenti' });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/pageviews/weekly-top-pages', authenticate_noerror, async (req, res) => {
|
||||
const { idapp, userId, unique, year, week } = req.query;
|
||||
|
||||
try {
|
||||
const matchStage = { idapp };
|
||||
if (userId) {
|
||||
matchStage.$or = [{ userId }, { username: userId }];
|
||||
}
|
||||
|
||||
const pipeline = [];
|
||||
|
||||
// Filtro base
|
||||
pipeline.push({ $match: matchStage });
|
||||
|
||||
// Estrai settimana e anno
|
||||
pipeline.push({
|
||||
$addFields: {
|
||||
week: { $isoWeek: '$timestamp' },
|
||||
year: { $isoWeekYear: '$timestamp' },
|
||||
},
|
||||
});
|
||||
|
||||
// Filtra per settimana e anno se specificati
|
||||
if (year && week) {
|
||||
pipeline.push({
|
||||
$match: {
|
||||
year: parseInt(year),
|
||||
week: parseInt(week),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (unique === 'true') {
|
||||
// Visite uniche: 1 per utente/giorno/pagina
|
||||
pipeline.push({
|
||||
$group: {
|
||||
_id: {
|
||||
url: '$url',
|
||||
user: { $ifNull: ['$userId', '$ip'] },
|
||||
day: { $dateToString: { format: '%Y-%m-%d', date: '$timestamp' } },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Riformatta per conteggio
|
||||
pipeline.push({
|
||||
$group: {
|
||||
_id: '$_id.url',
|
||||
count: { $sum: 1 },
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// Visite totali: tutte le occorrenze
|
||||
pipeline.push({
|
||||
$group: {
|
||||
_id: '$url',
|
||||
count: { $sum: 1 },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Ordina per numero visite
|
||||
pipeline.push({ $sort: { count: -1 } });
|
||||
|
||||
// Aggiungi metadati settimana/anno se presenti
|
||||
if (year && week) {
|
||||
pipeline.push({
|
||||
$addFields: {
|
||||
year: parseInt(year),
|
||||
week: parseInt(week),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const result = await PageView.aggregate(pipeline);
|
||||
|
||||
res.json(
|
||||
result.map((r) => ({
|
||||
url: r._id,
|
||||
count: r.count,
|
||||
year: r.year,
|
||||
week: r.week,
|
||||
}))
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Errore nel calcolo delle statistiche settimanali' });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user