cobalt/src/modules/stream/manage.js

90 lines
2.6 KiB
JavaScript
Raw Normal View History

2022-07-08 19:17:56 +01:00
import NodeCache from "node-cache";
import { randomBytes } from "crypto";
import { nanoid } from 'nanoid';
2022-07-08 19:17:56 +01:00
import { decryptStream, encryptStream, generateHmac } from "../sub/crypto.js";
2022-07-08 19:17:56 +01:00
import { streamLifespan } from "../config.js";
const streamCache = new NodeCache({
stdTTL: streamLifespan/1000,
checkperiod: 10,
deleteOnExpire: true
})
2022-07-08 19:17:56 +01:00
streamCache.on("expired", (key) => {
streamCache.del(key);
})
const hmacSalt = randomBytes(64).toString('hex');
2022-07-08 19:17:56 +01:00
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();
2022-07-08 19:17:56 +01:00
}
export function verifyStream(id, hmac, exp, secret, iv) {
2022-07-08 19:17:56 +01:00
try {
const ghmac = generateHmac(`${id},${exp},${iv},${secret}`, hmacSalt);
if (ghmac !== String(hmac)) {
return {
error: "i couldn't verify if you have access to this stream. go back and try again!",
status: 401
}
}
const streamInfo = JSON.parse(decryptStream(streamCache.get(id.toString()), iv, secret));
if (!streamInfo) return {
error: "this download link has expired or doesn't exist. go back and try again!",
status: 400
}
if (String(exp) === String(streamInfo.exp) && Number(exp) > new Date().getTime()) {
return streamInfo;
}
return {
error: "i couldn't verify if you have access to this stream. go back and try again!",
status: 401
}
2022-07-08 19:17:56 +01:00
} catch (e) {
return { status: 500, body: { status: "error", text: "couldn't verify this stream. request a new one!" } };
2022-07-08 19:17:56 +01:00
}
}