From ad419f38b061f4baa8a5c5ed897140e438d765c5 Mon Sep 17 00:00:00 2001 From: ayrisdev Date: Sun, 30 Aug 2026 15:54:51 +0300 Subject: [PATCH] =?UTF-8?q?debug:=20yt-dlp=20live-check=20hatalar=C4=B1n?= =?UTF-8?q?=C4=B1=20/status'ta=20g=C3=B6r=C3=BCn=C3=BCr=20k=C4=B1l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit yt-dlp hem "kanal canlı değil" hem de gerçek bir hata (ağ engeli, bot tespiti, extractor kırılması) durumunda non-zero exit code veriyor; ikisi ayırt edilemiyordu. Son hata mesajı artık kanal başına saklanıp GET /status içinde lastPollError alanında dönüyor. Co-Authored-By: Claude Sonnet 5 --- apps/api-daemon/src/server.ts | 2 ++ apps/api-daemon/src/youtubePolling.ts | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/api-daemon/src/server.ts b/apps/api-daemon/src/server.ts index 4c151f8..18c6d4c 100644 --- a/apps/api-daemon/src/server.ts +++ b/apps/api-daemon/src/server.ts @@ -1,6 +1,7 @@ import express from "express"; import { prisma } from "@streamclipper/db"; import { env } from "./env"; +import { lastPollErrors } from "./youtubePolling"; export function startServer() { const app = express(); @@ -26,6 +27,7 @@ export function startServer() { lastCheckedAt: c.lastCheckedAt, recording: c.sessions.length > 0, activeSessionId: c.sessions[0]?.id ?? null, + lastPollError: lastPollErrors.get(c.channelId) ?? null, })), }); }); diff --git a/apps/api-daemon/src/youtubePolling.ts b/apps/api-daemon/src/youtubePolling.ts index bcc9452..6ad6c12 100644 --- a/apps/api-daemon/src/youtubePolling.ts +++ b/apps/api-daemon/src/youtubePolling.ts @@ -7,6 +7,14 @@ import { sendTelegramMessage } from "./telegram"; const execFileAsync = promisify(execFile); +/** + * yt-dlp exits non-zero both when a channel isn't live and when the check + * itself fails (network block, bot detection, extractor breakage). Those two + * cases must not be indistinguishable, so the last failure per channel is + * kept here and surfaced via GET /status for debugging. + */ +export const lastPollErrors = new Map(); + /** * Live detection goes through yt-dlp itself instead of the YouTube Data API. * `search.list?eventType=live` costs 100 quota units per call against a @@ -23,10 +31,12 @@ async function findLiveVideoId(channelId: string): Promise { ["--simulate", "--no-warnings", "--print", "%(id)s", liveUrl], { timeout: 20_000 }, ); + lastPollErrors.delete(channelId); const videoId = stdout.trim().split("\n")[0]; return videoId || null; - } catch { - // yt-dlp exits non-zero when the channel isn't currently live + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + lastPollErrors.set(channelId, message.slice(0, 500)); return null; } }