All checks were successful
news-summary-bot-cicd / build_push_deploy (push) Successful in 4m40s
- yt-dlp에 쿠키 파일(/app/cookies.txt) 지원 추가 (YouTube 봇 감지 우회) - CI/CD에 paths-ignore: **/*.md 추가하여 문서 수정 시 빌드 스킵 - 전체 문서 업데이트: 라우트 변경, 쿠키 인증 방식, n8n Expression 모드 안내 - .gitignore에 cookies.txt 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
104 lines
2.9 KiB
Markdown
104 lines
2.9 KiB
Markdown
# News Summary Bot
|
|
|
|
YouTube 뉴스/경제 채널의 새 영상을 감지하면 자막을 추출하고, Claude API로 요약한 뒤 Discord로 전송하는 봇입니다.
|
|
|
|
## 아키텍처
|
|
|
|
```
|
|
n8n (RSS 감지) → POST /api/news/summarize → 자막 추출 → Claude 요약 → Discord 웹훅
|
|
```
|
|
|
|
| 모듈 | 역할 |
|
|
|------|------|
|
|
| `app/main.py` | FastAPI 엔드포인트 |
|
|
| `app/transcript.py` | YouTube 자막 추출 (yt-dlp + 쿠키 인증) |
|
|
| `app/summarizer.py` | Claude Sonnet 4.6으로 요약 생성 |
|
|
| `app/discord.py` | Discord 웹훅 전송 |
|
|
| `app/config.py` | 환경변수 설정 (pydantic-settings) |
|
|
|
|
## 빠른 시작
|
|
|
|
### 환경변수 설정
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
# .env 파일에서 아래 값을 수정
|
|
```
|
|
|
|
| 변수 | 필수 | 설명 |
|
|
|------|------|------|
|
|
| `ANTHROPIC_API_KEY` | O | Claude API 키 |
|
|
| `DISCORD_WEBHOOK_URL` | O | Discord 웹훅 URL |
|
|
| `API_SECRET` | X | n8n → FastAPI 인증용 시크릿 |
|
|
|
|
### 로컬 개발
|
|
|
|
```bash
|
|
pip install -r requirements.txt
|
|
uvicorn app.main:app --reload
|
|
```
|
|
|
|
### Docker
|
|
|
|
```bash
|
|
docker build -t nkey/news-summary-bot .
|
|
docker compose up
|
|
```
|
|
|
|
### 쿠키 파일 (서버 배포 시 필수)
|
|
|
|
OCI 등 클라우드 서버에서는 YouTube가 데이터센터 IP를 봇으로 감지하여 자막 추출을 차단합니다. 이를 우회하기 위해 쿠키 파일이 필요합니다.
|
|
|
|
1. Chrome 확장 **Get cookies.txt LOCALLY**로 YouTube 쿠키 export
|
|
2. 서버에 `cookies.txt` 업로드
|
|
3. `compose.apps.yml`에서 볼륨 마운트: `./news-summary-bot/cookies.txt:/app/cookies.txt:ro`
|
|
|
|
> 쿠키는 6개월~1년 후 만료됩니다. 자막 추출 500 에러 발생 시 쿠키 재export가 필요합니다.
|
|
|
|
## API
|
|
|
|
### `POST /api/news/summarize` (외부) / `POST /summarize` (내부)
|
|
|
|
영상 URL을 받아 자막 추출 → 요약 → Discord 전송을 수행합니다.
|
|
|
|
**Request:**
|
|
|
|
```json
|
|
{
|
|
"video_url": "https://youtu.be/xxx",
|
|
"title": "영상 제목"
|
|
}
|
|
```
|
|
|
|
`API_SECRET` 설정 시 헤더에 `X-Api-Secret` 포함 필요.
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"status": "ok",
|
|
"title": "영상 제목",
|
|
"summary_length": 1234
|
|
}
|
|
```
|
|
|
|
### `GET /api/news/health` (외부) / `GET /health` (내부)
|
|
|
|
헬스 체크 엔드포인트.
|
|
|
|
> **참고:** Nginx가 `/api/news/` prefix를 strip하므로, FastAPI 내부 라우트는 `/summarize`, `/health`입니다. 외부에서는 `/api/news/summarize`, `/api/news/health`로 접근합니다.
|
|
|
|
## n8n 워크플로우
|
|
|
|
```
|
|
RSS Feed Trigger (채널A) ──┐
|
|
├→ Merge → HTTP Request (POST /api/news/summarize)
|
|
RSS Feed Trigger (채널B) ──┘
|
|
```
|
|
|
|
n8n에서 RSS Feed Trigger로 채널별 새 영상을 감지하고, 각 영상마다 이 봇의 API를 호출합니다. 자세한 설정은 [docs/n8n-setup.md](docs/n8n-setup.md)를 참고하세요.
|
|
|
|
## 배포
|
|
|
|
Docker Hub에 이미지를 푸시하고 서버에서 `docker compose pull && docker compose up -d`로 배포합니다. 자세한 내용은 [docs/operations.md](docs/operations.md)를 참고하세요.
|