diff --git a/src/server.js b/src/server.js index 8003298..a37c4a6 100644 --- a/src/server.js +++ b/src/server.js @@ -1,10 +1,26 @@ const path = require('path'); +const crypto = require('crypto'); const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000; -const STREAM_URL = process.env.HLS_URL || 'https://folxplay.b-cdn.net/live/stream1_master.m3u8'; +// Our Bunny CDN pull zone (separate from Rok's folxplay zone) +const BUNNY_HOST = 'https://folxlive.b-cdn.net'; +const BUNNY_KEY = process.env.BUNNY_SECURITY_KEY || '492fb7b3-8a1d-4a78-8e9e-fae8c07af195'; + +function signBunnyUrl(urlPath, expiresInSeconds = 3600) { + const expires = Math.floor(Date.now() / 1000) + expiresInSeconds; + const hash = crypto.createHash('sha256').update(BUNNY_KEY + urlPath + expires).digest(); + const token = hash.toString('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, ''); + return { token, expires, url: `${BUNNY_HOST}${urlPath}?token=${token}&expires=${expires}` }; +} + +// Default: stream1 master (linear, non-DVR) +const DEFAULT_HLS_PATH = process.env.HLS_PATH || '/live/stream1_master.m3u8'; app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, '..', 'views')); @@ -15,18 +31,31 @@ app.use(express.static(path.join(__dirname, '..', 'public'), { })); app.get('/', (_req, res) => { - res.render('index', { hlsUrl: STREAM_URL }); + const { url } = signBunnyUrl(DEFAULT_HLS_PATH, 3600); + res.render('index', { hlsUrl: url }); }); app.get('/test-embed', (_req, res) => { res.render('test-embed'); }); +// Token-signed master proxy: GET /stream/:n/master.m3u8 → signed Bunny URL +// Optional ?dvr=1 for DVR variant +app.get('/stream/:n/master.m3u8', (req, res) => { + const n = req.params.n; + if (!/^[1-6]$/.test(n)) return res.status(400).send('Invalid stream number'); + const dvr = req.query.dvr === '1' ? '_dvr' : ''; + const streamPath = `/live/stream${n}_master${dvr}.m3u8`; + const { url } = signBunnyUrl(streamPath, 3600); + res.redirect(302, url); +}); + app.get('/api/health', (_req, res) => { - res.json({ ok: true, hls: STREAM_URL, ts: Date.now() }); + res.json({ ok: true, host: BUNNY_HOST, defaultPath: DEFAULT_HLS_PATH, ts: Date.now() }); }); app.listen(PORT, () => { console.log(`[folx-live] listening on :${PORT}`); - console.log(`[folx-live] HLS source: ${STREAM_URL}`); + console.log(`[folx-live] CDN host: ${BUNNY_HOST}`); + console.log(`[folx-live] Default stream path: ${DEFAULT_HLS_PATH}`); }); diff --git a/views/index.ejs b/views/index.ejs index f5cddab..00f9286 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -506,7 +506,21 @@