feat: interaktif panel kontrolleri (Faz 3)

Yayın durdurma, kanal duraklat/devam (tekli+toplu), şimdi kontrol et,
manuel URL ile zorla kayıt başlatma, canlı player+log önizleme, oturum
süre sayacı, başarısız/takılı render için tekrar dene ve iptal, poll
aralığı + ham segment TTL'yi panelden canlı değiştirme, cookie bayatlık
uyarısı, Telegram bildirim aç/kapa, ve kullanım/maliyet özeti (/stats).

api-daemon'ın yeni state-değiştiren endpoint'leri (stop/force-start/
render/cancel) INTERNAL_API_TOKEN ile korunuyor — bu daemon'ın portu
Coolify'de public'e açık olduğu için korumasız bırakmak güvenlik açığı
olurdu.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-02 13:38:47 +03:00
co-authored by Claude Sonnet 5
parent 2fc3254d64
commit 43ccbd9ec7
23 changed files with 742 additions and 75 deletions
+7
View File
@@ -21,6 +21,13 @@ async def get_pool() -> asyncpg.Pool:
return _pool
async def get_setting(key: str, default: str | None = None) -> str | None:
"""Same app_settings table the Node side reads for cookies/poll-interval — settings authored from the panel are shared across both languages."""
pool = await get_pool()
row = await pool.fetchrow("SELECT value FROM app_settings WHERE key = $1", key)
return row["value"] if row else default
async def get_raw_segment(raw_segment_id: str) -> asyncpg.Record | None:
pool = await get_pool()
return await pool.fetchrow(
+2 -1
View File
@@ -245,7 +245,8 @@ async def process_video_render(job, job_token=None):
)
await db.update_short_video(short_id, status="READY", file_path=out_path)
await send_telegram_message(f"🎬 *{candidate['channel_name']}* için 9:16 kısa video hazır!")
if await db.get_setting("notify_render_done", "true") != "false":
await send_telegram_message(f"🎬 *{candidate['channel_name']}* için 9:16 kısa video hazır!")
print(f"[video-render] short {short_id} ready: {out_path}")
except Exception as exc:
print(f"[video-render] failed for candidate {candidate_id}: {exc}")