fp/services/scout/src/ytdlp.ts
CJ_Clippy 5af878c3a3
Some checks failed
ci / build (push) Failing after 1s
refactor for simpler controlflow
2024-09-25 18:01:25 -08:00

65 lines
2.2 KiB
TypeScript

import spawnWrapper from './spawnWrapper.ts'
import 'dotenv/config'
import { configs } from './config.ts'
const maxRetries = 3
export class ExhaustedRetriesError extends Error {
constructor(message?: string) {
super(message)
Object.setPrototypeOf(this, ExhaustedRetriesError.prototype)
this.name = this.constructor.name
this.message = `ExhaustedRetries: We retried the request the maximum amount of times. maxRetries of ${maxRetries} was reached.`
}
getErrorMessage() {
return this.message
}
}
export class RoomOfflineError extends Error {
constructor(message?: string) {
super(message)
Object.setPrototypeOf(this, RoomOfflineError.prototype)
this.name = this.constructor.name
this.message = `RoomOffline. ${this.message}`
}
getErrorMessage() {
return this.message
}
}
export async function getPlaylistUrl (roomUrl: string, proxy = false, retries = 0): Promise<string|null> {
console.log(`getPlaylistUrl roomUrl=${roomUrl} proxy=${false} retries=${retries}`)
let args = ['-4', '-g', roomUrl]
if (proxy) {
console.log(`proxy=${proxy}, HTTP_PROXY=${configs.httpProxy}`)
args = args.concat(['--proxy', configs.httpProxy])
}
const { code, output } = await spawnWrapper('yt-dlp', args)
if (output.match(/HTTP Error 403/)) {
// we were likely blocked by Cloudflare
// we make the request a second time, this time via proxy
if (retries < maxRetries) return getPlaylistUrl(roomUrl, true, retries+=1);
else throw new ExhaustedRetriesError();
} else if (output.match(/Unable to find stream URL/)) {
// sometimes this happens. a retry is in order.
if (retries < maxRetries) return getPlaylistUrl(roomUrl, proxy, retries+=1);
else throw new ExhaustedRetriesError()
} else if (code === 0 && output.match(/https:\/\/.*\.m3u8/)) {
// this must be an OK result with a playlist
return output.trim()
} else if (code === 1 && output.match(/Room is currently offline/)) {
throw new RoomOfflineError()
} else {
console.error('exotic scenario')
const msg = `We encountered an exotic scenario where code=${code} and output=${output}. Admin: please patch the code to handle this scenario.`
console.error(msg)
throw new Error(msg)
}
}
export default {
getPlaylistUrl
}