Changeset 834bcc3 in Klonkt for src/routes/download.js
- Timestamp:
- 06/23/2026 06:14:27 PM (3 months ago)
- Branches:
- main
- Children:
- d774679
- Parents:
- bb42dfb
- File:
-
- 1 edited
-
src/routes/download.js (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/download.js
rbb42dfb r834bcc3 1 1 /** 2 * Download- voor-email (premium feature #2).2 * Download-for-email (premium feature #2). 3 3 * 4 * GET /downloads -> li jst van downloadbare tracks (premium; anders 404)5 * GET /download/:id -> e -mail-capture-pagina voor ééntrack6 * POST /download/:id -> e-mail opslaan (-> mailinglijst) + download vrijgeven7 * GET /download/:id/bestand -> serve ert het bestand (sessie-gated nacapture)4 * GET /downloads -> list of downloadable tracks (premium; 404 otherwise) 5 * GET /download/:id -> email capture page for a single track 6 * POST /download/:id -> save email (-> mailing list) + unlock download 7 * GET /download/:id/bestand -> serves the file (session-gated after capture) 8 8 * 9 * De fan laat z'n e-mail achter en krijgt het bestand; het adres komt in de10 * subscribers -lijst (source 'download', single opt-in — geen confirm-drempel vóór de9 * The fan leaves their email and receives the file; the address is added to the 10 * subscribers list (source 'download', single opt-in — no confirm step before the 11 11 * download). Hub: via /user/:slug/... (resolveSite + siteUrlBase). 12 12 */ … … 24 24 const router = express.Router(); 25 25 26 // Als er een echte (gepinde) post met slug 'downloads' bestaat, hangt de27 // downloads-lijst feitelijk aan die post. Dan tonen we óók de Newer/Older-postnav,28 // zodat de bezoeker net als bij een post verder kan bladeren.26 // If a real (pinned) post with slug 'downloads' exists, the downloads list is 27 // effectively attached to that post. We then also show the Newer/Older post nav 28 // so the visitor can browse just like on a regular post. 29 29 function downloadsPostNav(req, res) { 30 30 const site = res.locals.site; … … 40 40 41 41 const MIME = { '.mp3': 'audio/mpeg', '.wav': 'audio/wav', '.flac': 'audio/flac', '.m4a': 'audio/mp4', '.ogg': 'audio/ogg' }; 42 const GRACE_MS = 15 * 60 * 1000; // download -venster nacapture42 const GRACE_MS = 15 * 60 * 1000; // download window after capture 43 43 44 44 function dlTrack(siteId, id) { … … 55 55 } 56 56 57 // Li jst van downloadbare tracks.57 // List of downloadable tracks. 58 58 router.get('/downloads', (req, res, next) => { 59 59 if (!premiumUnlocked()) return next(); … … 67 67 renderPage(req, res, 'pages/downloads', { 68 68 pageTitle: 'Downloads — ' + (site.title || ''), 69 // on-special = compact e profielkop (zoals op een post); on-downloads = pill grijs70 // + feature-route -gedrag. Samen → downloads ziet er net zo uit als eenpost.69 // on-special = compact profile header (like on a post); on-downloads = grey pill 70 // + feature-route behaviour. Together → downloads looks just like a post. 71 71 bodyClass: 'on-downloads on-special', 72 72 dlTracks: tracks, … … 76 76 }); 77 77 78 // Capture -pagina voor ééntrack.78 // Capture page for a single track. 79 79 router.get('/download/:id', (req, res, next) => { 80 80 if (!premiumUnlocked()) return next(); … … 93 93 }); 94 94 95 // E-mail opslaan + download vrijgeven.95 // Save email + unlock download. 96 96 router.post('/download/:id', (req, res, next) => { 97 97 if (!premiumUnlocked()) return next(); … … 109 109 }); 110 110 } 111 // Download vrijgeven in de sessie (kort venster).111 // Unlock download in the session (short window). 112 112 if (!req.session.dl) req.session.dl = {}; 113 113 req.session.dl[track.id] = Date.now(); … … 118 118 }); 119 119 120 // Het bestand serveren — alleen als er net een e-mail is achtergelaten (sessie).120 // Serve the file — only if an email was just submitted (session-gated). 121 121 router.get('/download/:id/bestand', (req, res, next) => { 122 122 if (!premiumUnlocked()) return next(); … … 129 129 return res.status(403).send('Laat eerst je e-mailadres achter om te downloaden.'); 130 130 } 131 // De speelbare/te-downloaden file = de KALE filename (storage_path is een132 // absolu ut pad → faalt de slash-guard). Zelfde aanpak als /audio/stream.131 // The playable/downloadable file = the BARE filename (storage_path is an 132 // absolute path → fails the slash-guard). Same approach as /audio/stream. 133 133 const sp = track.filename; 134 134 if (!sp || sp.includes('/') || sp.includes('\\') || sp.includes('..')) return res.status(400).send('Bad path');
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)