Files
news-summary-bot/app/main.py
sm4640 8aa03232e8
Some checks failed
news-summary-bot-cicd / build_push_deploy (push) Has been cancelled
Fix: [3.0.3] JSON 파싱 강화 + Discord 전송 안정화
- summarizer: 코드펜스/잡텍스트 포함된 Claude 응답도 안정적으로 파싱
- summarizer: 프롬프트에 코드펜스 금지 명시
- main: Discord embed용 summary 통합 필드 추가
- docs: n8n Discord 노드를 JSON.stringify() 방식으로 변경 (줄바꿈/따옴표 이스케이프)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 19:56:06 +09:00

60 lines
1.7 KiB
Python

from fastapi import FastAPI, Header, HTTPException
from pydantic import BaseModel
from app.config import settings
from app.summarizer import summarize
from app.transcript import SkipVideo, extract_video_id, fetch_transcript
app = FastAPI(title="News Summary Bot")
class SummarizeRequest(BaseModel):
video_url: str
title: str = ""
channel_name: str = ""
@app.post("/summarize")
async def summarize_video(
req: SummarizeRequest,
x_api_secret: str = Header(default=""),
):
if settings.api_secret and x_api_secret != settings.api_secret:
raise HTTPException(status_code=401, detail="Unauthorized")
title = req.title or "제목 없음"
channel_name = req.channel_name or ""
base = {"video_url": req.video_url, "title": title, "channel_name": channel_name}
try:
video_id = extract_video_id(req.video_url)
transcript = fetch_transcript(video_id)
summary = summarize(transcript, title)
except SkipVideo as e:
return {**base, "status": "skipped", "reason": str(e)}
except Exception as e:
return {
**base,
"status": "error",
"error_type": type(e).__name__,
"error_message": str(e),
}
# Discord embed description용 통합 요약
parts = []
if summary.get("oneliner"):
parts.append(f"**{summary['oneliner']}**")
if summary.get("main_points"):
parts.append(f"\n{summary['main_points']}")
if summary.get("conclusion"):
parts.append(f"\n> {summary['conclusion']}")
summary["summary"] = "\n".join(parts)
return {**base, "status": "ok", **summary}
@app.get("/health")
async def health():
return {"status": "ok"}