Changeset d549549 in Klonkt for src/routes/audio.js


Ignore:
Timestamp:
06/16/2026 09:41:28 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
029f047
Parents:
3f893bf
Message:

Statistics module (Phase 3): cookie-free tracking + premium stats page

Counters: posts.view_count, audio_tracks.play_count, stat_daily
(pageviews/day) + stat_visitor_day (unique visitors via daily rotating
salted hash of IP+UA, never stored → no cookie, no consent needed).
StatsService records pageview on home + post-view (skips admins), play on
the initial player stream fetch. /admin/stats (god-only +
premiumUnlocked-gated): cards + 14-day cookie-free bar chart
(visitors/views) + top posts/tracks. Dashboard button is premium-gated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/audio.js

    r3f893bf rd549549  
    2828import path from 'path';
    2929import { fileURLToPath } from 'url';
     30import db from '../config/database.js';
     31import { recordPlay } from '../services/StatsService.js';
    3032
    3133const __dirname = path.dirname(fileURLToPath(import.meta.url));
     
    9092  const range = req.headers.range;
    9193
     94  // Statistieken: tel één play bij de initiële player-fetch (niet bij scrub/
     95  // range-continuaties; replays binnen 24u komen uit de browsercache → geen
     96  // dubbeltelling). Best-effort, mag nooit de stream breken.
     97  if (req.get('X-Audio-Player') === '1' && (!range || /^bytes=0-/.test(range))) {
     98    try {
     99      const tr = db.prepare(`
     100        SELECT t.id FROM audio_tracks t JOIN media m ON t.media_id = m.id
     101        WHERE m.storage_path = ? OR m.storage_path LIKE ? LIMIT 1
     102      `).get(filename, '%' + filename);
     103      if (tr) recordPlay(tr.id);
     104    } catch {}
     105  }
     106
    92107  // Common headers
    93108  res.setHeader('Content-Type', mime);
Note: See TracChangeset for help on using the changeset viewer.