feat: YouTube cookie'lerini panelden yönetilebilir hale getir
Cookie'ler saatler içinde eskiyordu, her seferinde manuel Coolify env güncellemesi + redeploy gerekiyordu. Artık DB'de (app_settings tablosu) tutuluyor; /settings sayfasından yeni cookies.txt yapıştırılıp kaydedilebiliyor, bir sonraki yt-dlp çağrısında redeploy gerekmeden devreye giriyor. YTDLP_COOKIES_B64 env var mekanizması kaldırıldı. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -90,7 +90,7 @@ async function runCapture(job: Job<StreamIngestJob>): Promise<void> {
|
||||
"yt-dlp",
|
||||
[
|
||||
"--js-runtimes", "node",
|
||||
...ytdlpAntiBotArgs(),
|
||||
...(await ytdlpAntiBotArgs()),
|
||||
"-f", "bestvideo+bestaudio/best", "-o", "-", youtubeUrl,
|
||||
],
|
||||
{ stdio: ["ignore", "pipe", "pipe"] },
|
||||
|
||||
@@ -7,7 +7,6 @@ export const env = {
|
||||
segmentTimeSec: Number(process.env.SEGMENT_TIME_SEC ?? 900),
|
||||
port: Number(process.env.API_DAEMON_PORT ?? 4001),
|
||||
forceLiveUrl: process.env.FORCE_LIVE_URL ?? "",
|
||||
ytdlpCookiesB64: process.env.YTDLP_COOKIES_B64 ?? "",
|
||||
ytdlpPotProviderUrl: process.env.YTDLP_POT_PROVIDER_URL ?? "",
|
||||
maxConcurrentCaptures: Number(process.env.MAX_CONCURRENT_CAPTURES ?? 10),
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ async function findLiveVideoId(channelId: string): Promise<string | null> {
|
||||
try {
|
||||
const { stdout } = await execFileAsync(
|
||||
"yt-dlp",
|
||||
["--simulate", "--no-warnings", ...ytdlpAntiBotArgs(), "--print", "%(id)s", liveUrl],
|
||||
["--simulate", "--no-warnings", ...(await ytdlpAntiBotArgs()), "--print", "%(id)s", liveUrl],
|
||||
{ timeout: 20_000 },
|
||||
);
|
||||
lastPollErrors.delete(channelId);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { writeFileSync } from "node:fs";
|
||||
import { prisma } from "@streamclipper/db";
|
||||
import { env } from "./env";
|
||||
|
||||
const COOKIES_PATH = "/tmp/yt-cookies.txt";
|
||||
const COOKIES_SETTING_KEY = "ytdlp_cookies";
|
||||
|
||||
/**
|
||||
* YouTube's anti-bot layer against datacenter IPs has two parts, both
|
||||
@@ -9,21 +11,20 @@ const COOKIES_PATH = "/tmp/yt-cookies.txt";
|
||||
* with an authenticated session's cookies) and a "The page needs to be
|
||||
* reloaded" proof-of-origin token check (avoided by querying the
|
||||
* bgutil-ytdlp-pot-provider sidecar — see docker-compose.yml sc_pot_provider).
|
||||
* The cookies file is never committed — it's decoded once at startup from a
|
||||
* Coolify-managed env var into a local temp file.
|
||||
*
|
||||
* Cookies rotate/expire over hours, so they're stored in the DB (updated
|
||||
* from the panel's Settings page — see apps/frontend/app/settings) rather
|
||||
* than baked in at container start from an env var. Every call re-reads the
|
||||
* current value and rewrites the temp file, so a panel update takes effect
|
||||
* on the very next yt-dlp invocation without a redeploy.
|
||||
*/
|
||||
const cookiesFilePath: string | null = env.ytdlpCookiesB64
|
||||
? (() => {
|
||||
writeFileSync(COOKIES_PATH, Buffer.from(env.ytdlpCookiesB64, "base64"), { mode: 0o600 });
|
||||
return COOKIES_PATH;
|
||||
})()
|
||||
: null;
|
||||
|
||||
export function ytdlpAntiBotArgs(): string[] {
|
||||
export async function ytdlpAntiBotArgs(): Promise<string[]> {
|
||||
const args: string[] = [];
|
||||
|
||||
if (cookiesFilePath) {
|
||||
args.push("--cookies", cookiesFilePath);
|
||||
const setting = await prisma.appSetting.findUnique({ where: { key: COOKIES_SETTING_KEY } });
|
||||
if (setting?.value) {
|
||||
writeFileSync(COOKIES_PATH, setting.value, { mode: 0o600 });
|
||||
args.push("--cookies", COOKIES_PATH);
|
||||
}
|
||||
|
||||
if (env.ytdlpPotProviderUrl) {
|
||||
|
||||
Reference in New Issue
Block a user