| 1 | /**
|
|---|
| 2 | * Admin: Statistics (premium module, god-only).
|
|---|
| 3 | *
|
|---|
| 4 | * GET /admin/stats -> cookie-free statistics: visitors/views per day,
|
|---|
| 5 | * plays, and the most popular posts/tracks.
|
|---|
| 6 | *
|
|---|
| 7 | * Premium-gated via premiumUnlocked() (premium layer off = freely available;
|
|---|
| 8 | * on = Patreon required). Tracking is in StatsService (no cookies).
|
|---|
| 9 | */
|
|---|
| 10 |
|
|---|
| 11 | import express from 'express';
|
|---|
| 12 | import db from '../config/database.js';
|
|---|
| 13 | import { renderPage } from '../middleware/render.js';
|
|---|
| 14 | import { requireGod } from '../middleware/auth.js';
|
|---|
| 15 | import { premiumUnlocked } from '../services/PatreonService.js';
|
|---|
| 16 | import { getStats } from '../services/StatsService.js';
|
|---|
| 17 |
|
|---|
| 18 | const router = express.Router();
|
|---|
| 19 |
|
|---|
| 20 | router.get('/', requireGod, (req, res) => {
|
|---|
| 21 | if (!premiumUnlocked()) {
|
|---|
| 22 | return res.status(403).send('Statistieken is een premium-functie — koppel Patreon in Beheer → Instellingen.');
|
|---|
| 23 | }
|
|---|
| 24 | // Link-in-bio clicks (premium #6) for the current site.
|
|---|
| 25 | let linkClicks = [];
|
|---|
| 26 | if (res.locals.site) {
|
|---|
| 27 | try {
|
|---|
| 28 | linkClicks = db.prepare(
|
|---|
| 29 | 'SELECT url, clicks FROM link_clicks WHERE site_id = ? AND clicks > 0 ORDER BY clicks DESC LIMIT 50'
|
|---|
| 30 | ).all(res.locals.site.id);
|
|---|
| 31 | } catch { linkClicks = []; }
|
|---|
| 32 | }
|
|---|
| 33 | const days = [7, 14, 30, 90].includes(parseInt(req.query.days, 10)) ? parseInt(req.query.days, 10) : 14;
|
|---|
| 34 | renderPage(req, res, 'pages/admin-stats', {
|
|---|
| 35 | pageTitle: 'Statistieken',
|
|---|
| 36 | bodyClass: 'on-admin',
|
|---|
| 37 | stats: getStats(days),
|
|---|
| 38 | linkClicks,
|
|---|
| 39 | });
|
|---|
| 40 | });
|
|---|
| 41 |
|
|---|
| 42 | export default router;
|
|---|