diff --git a/.env.development b/.env.development index 7013049..076722d 100644 --- a/.env.development +++ b/.env.development @@ -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" \ No newline at end of file diff --git a/src/server/models/PageView.js b/src/server/models/PageView.js new file mode 100755 index 0000000..ba8c2e6 --- /dev/null +++ b/src/server/models/PageView.js @@ -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); \ No newline at end of file diff --git a/src/server/router/api_router.js b/src/server/router/api_router.js index e4ceb48..b02ccd0 100644 --- a/src/server/router/api_router.js +++ b/src/server/router/api_router.js @@ -1,27 +1,259 @@ -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; + const timeout = req.body.timeout; - console.log(`πŸ•™ Richiesta iniziata con timeout=${timeout}`); - - // Simuliamo un'elaborazione lunga - const durataMs = timeout - 2000; - setTimeout(() => { - console.log(`βœ… Elaborazione completata di ${durataMs} ms`); - res.json({ ok: true, message: `βœ… Richiesta completata con successo! (${durataMs})` }); - }, durataMs); - - // 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!' }); + console.log(`πŸ•™ Richiesta iniziata con timeout=${timeout}`); + + // Simuliamo un'elaborazione lunga + const durataMs = timeout - 2000; + setTimeout(() => { + console.log(`βœ… Elaborazione completata di ${durataMs} ms`); + res.json({ ok: true, message: `βœ… Richiesta completata con successo! (${durataMs})` }); + }, durataMs); + + // 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!" }); + } + }, 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, + }); + + 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 }); } - }, durataMs + 1000); - }); + }); + + // 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; -