websync / pages /api /source.ts
Shivam
Initial commit: Web-SyncPlay moved into Streamer
d092f57
import { NextApiRequest, NextApiResponse } from "next"
import { isUrl, shellSanitizeUrl } from "../../lib/utils"
import { exec, ExecException } from "child_process"
import * as util from "util"
const asyncExec = util.promisify(exec)
const memoizeExtractFromUrl = () => {
let cache: Record<string, any> = {}
return async (url: string) => {
if (url in cache) {
const cached = cache[url]
if (cached.pending) {
return true
}
return cache[url]
}
if (!isUrl(url)) {
console.error("Invalid url provided to source video from:", url)
cache[url] = {
error: true,
stdout: "",
stderr: "Invalid url",
}
return cache[url]
}
try {
cache[url] = await asyncExec("yt-dlp -g " + url)
} catch (error) {
const e = error as ExecException
console.error("Extraction failed", e)
cache[url] = {
error: true,
stdout: "",
stderr: e.message,
}
}
return cache[url]
}
}
const extractFromUrl = memoizeExtractFromUrl()
const handleResult = async (url: string, res: NextApiResponse) => {
const result = await extractFromUrl(url)
// already pending?
if (result === true) {
setTimeout(async () => {
await handleResult(url, res)
}, 100)
return
}
if (result.error) {
console.error(`exec error: ${result.error}`)
return res.status(500).send(result.stderr.replace("\n", ""))
}
res.json({
stdout: result.stdout,
stderr: result.stderr.replace("\n", ""),
})
}
export default async function source(
req: NextApiRequest,
res: NextApiResponse
) {
const url = shellSanitizeUrl(req.body)
if (!isUrl(url)) {
return res.status(400).send("Invalid url")
}
console.log("Requested video source of", req.body, "sanitized", url)
await handleResult(url, res)
}