import NodeCache from "node-cache"; import { randomBytes } from "crypto"; import { nanoid } from 'nanoid'; import { decryptStream, encryptStream, generateHmac } from "../sub/crypto.js"; import { streamLifespan } from "../config.js"; const streamNoAccess = { error: "i couldn't verify if you have access to this stream. go back and try again!", status: 401 } const streamNoExist = { error: "this download link has expired or doesn't exist. go back and try again!", status: 400 } const streamCache = new NodeCache({ stdTTL: streamLifespan/1000, checkperiod: 10, deleteOnExpire: true }) streamCache.on("expired", (key) => { streamCache.del(key); }) const hmacSalt = randomBytes(64).toString('hex'); export function createStream(obj) { const streamID = nanoid(), iv = randomBytes(16).toString('base64url'), secret = randomBytes(32).toString('base64url'), exp = new Date().getTime() + streamLifespan, hmac = generateHmac(`${streamID},${exp},${iv},${secret}`, hmacSalt), streamData = { exp: exp, type: obj.type, urls: obj.u, service: obj.service, filename: obj.filename, audioFormat: obj.audioFormat, isAudioOnly: !!obj.isAudioOnly, copy: !!obj.copy, mute: !!obj.mute, metadata: obj.fileMetadata || false }; streamCache.set( streamID, encryptStream(streamData, iv, secret) ) let streamLink = new URL('/api/stream', process.env.API_URL); const params = { 't': streamID, 'e': exp, 'h': hmac, 's': secret, 'i': iv } for (const [key, value] of Object.entries(params)) { streamLink.searchParams.append(key, value); } return streamLink.toString(); } export function verifyStream(id, hmac, exp, secret, iv) { try { const ghmac = generateHmac(`${id},${exp},${iv},${secret}`, hmacSalt); const cache = streamCache.get(id.toString()); if (ghmac !== String(hmac)) return streamNoAccess; if (!cache) return streamNoExist; const streamInfo = JSON.parse(decryptStream(cache, iv, secret)); if (!streamInfo) return streamNoExist; if (Number(exp) <= new Date().getTime()) return streamNoExist; return streamInfo; } catch (e) { return { error: "something went wrong and i couldn't verify this stream. go back and try again!", status: 500 } } }