Merge branch 'wukko:current' into current

This commit is contained in:
Solyn 2024-04-29 00:17:58 +01:00 committed by GitHub
commit ca34525fac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 30 deletions

View File

@ -131,14 +131,14 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) {
const checkBaseLength = q.t.length === 21 && q.e.length === 13; const checkBaseLength = q.t.length === 21 && q.e.length === 13;
const checkSafeLength = q.h.length === 43 && q.s.length === 43 && q.i.length === 22; const checkSafeLength = q.h.length === 43 && q.s.length === 43 && q.i.length === 22;
if (checkQueries && checkBaseLength && checkSafeLength) { if (checkQueries && checkBaseLength && checkSafeLength) {
let streamInfo = verifyStream(q.t, q.h, q.e, q.s, q.i);
if (streamInfo.error) {
return res.status(streamInfo.status).json(apiJSON(0, { t: streamInfo.error }).body);
}
if (q.p) { if (q.p) {
return res.status(200).json({ return res.status(200).json({
status: "continue" status: "continue"
}); })
}
let streamInfo = verifyStream(q.t, q.h, q.e, q.s, q.i);
if (streamInfo.error) {
return res.status(streamInfo.status).json(apiJSON(0, { t: streamInfo.error }).body);
} }
return stream(res, streamInfo); return stream(res, streamInfo);
} }

View File

@ -6,6 +6,8 @@ import { decryptStream, encryptStream, generateHmac } from "../sub/crypto.js";
import { streamLifespan } from "../config.js"; import { streamLifespan } from "../config.js";
import { strict as assert } from "assert"; import { strict as assert } from "assert";
const M3U_SERVICES = ['dailymotion', 'vimeo', 'rutube'];
const streamNoAccess = { const streamNoAccess = {
error: "i couldn't verify if you have access to this stream. go back and try again!", error: "i couldn't verify if you have access to this stream. go back and try again!",
status: 401 status: 401
@ -73,24 +75,28 @@ export function getInternalStream(id) {
return internalStreamCache[id]; return internalStreamCache[id];
} }
export function createInternalStream(obj = {}) { export function createInternalStream(url, obj = {}) {
assert(typeof obj.url === 'string'); assert(typeof url === 'string');
const streamID = nanoid(); const streamID = nanoid();
internalStreamCache[streamID] = { internalStreamCache[streamID] = {
url: obj.url, url,
service: obj.service, service: obj.service,
controller: new AbortController() controller: new AbortController()
}; };
let streamLink = new URL('/api/istream', `http://127.0.0.1:${process.env.API_PORT}`); let streamLink = new URL('/api/istream', `http://127.0.0.1:${process.env.API_PORT || 9000}`);
streamLink.searchParams.set('t', streamID); streamLink.searchParams.set('t', streamID);
return streamLink.toString(); return streamLink.toString();
} }
export function destroyInternalStream(url) { export function destroyInternalStream(url) {
const id = new URL(url).searchParams.get('t'); url = new URL(url);
assert(id); if (url.hostname !== '127.0.0.1') {
return;
}
const id = url.searchParams.get('t');
if (internalStreamCache[id]) { if (internalStreamCache[id]) {
internalStreamCache[id].controller.abort(); internalStreamCache[id].controller.abort();
@ -98,6 +104,28 @@ export function destroyInternalStream(url) {
} }
} }
function wrapStream(streamInfo) {
/* m3u8 links are currently not supported
* for internal streams, skip them */
if (M3U_SERVICES.includes(streamInfo.service)) {
return streamInfo;
}
const url = streamInfo.urls;
if (typeof url === 'string') {
streamInfo.urls = createInternalStream(url, streamInfo);
} else if (Array.isArray(url)) {
for (const idx in streamInfo.urls) {
streamInfo.urls[idx] = createInternalStream(
streamInfo.urls[idx], streamInfo
);
}
} else throw 'invalid urls';
return streamInfo;
}
export function verifyStream(id, hmac, exp, secret, iv) { export function verifyStream(id, hmac, exp, secret, iv) {
try { try {
const ghmac = generateHmac(`${id},${exp},${iv},${secret}`, hmacSalt); const ghmac = generateHmac(`${id},${exp},${iv},${secret}`, hmacSalt);
@ -113,25 +141,7 @@ export function verifyStream(id, hmac, exp, secret, iv) {
if (Number(exp) <= new Date().getTime()) if (Number(exp) <= new Date().getTime())
return streamNoExist; return streamNoExist;
if (!streamInfo.originalUrls) { return wrapStream(streamInfo);
streamInfo.originalUrls = streamInfo.urls;
}
if (typeof streamInfo.originalUrls === 'string') {
streamInfo.urls = createInternalStream({
url: streamInfo.originalUrls,
...streamInfo
});
} else if (Array.isArray(streamInfo.originalUrls)) {
for (const idx in streamInfo.originalUrls) {
streamInfo.originalUrls[idx] = createInternalStream({
url: streamInfo.originalUrls[idx],
...streamInfo
});
}
} else throw 'invalid urls';
return streamInfo;
} }
catch { catch {
return { return {