feat: v3 멀티플랫폼 자동화 엔진 — 변환/배포 엔진 + 쇼츠 + README

## 변환 엔진 (bots/converters/)
- blog_converter: HTML 자동감지 + Schema.org JSON-LD + AdSense 플레이스홀더
- card_converter: Pillow 1080×1080 인스타그램 카드 이미지
- thread_converter: X 스레드 280자 자동 분할
- newsletter_converter: 주간 HTML 뉴스레터
- shorts_converter: TTS + ffmpeg 뉴스앵커 쇼츠 영상 (1080×1920)

## 배포 엔진 (bots/distributors/)
- image_host: ImgBB 업로드 / 로컬 HTTP 서버
- instagram_bot: Instagram Graph API (컨테이너 → 폴링 → 발행)
- x_bot: X API v2 OAuth1 스레드 게시
- tiktok_bot: TikTok Content Posting API v2 청크 업로드
- youtube_bot: YouTube Data API v3 재개가능 업로드

## 기타
- article_parser: KEY_POINTS 파싱 추가 (SNS/TTS용 핵심 3줄)
- publisher_bot: HTML 본문 직접 발행 지원
- scheduler: 시차 배포 스케줄 + Telegram 변환/배포 명령 추가
- remote_claude: Claude Agent SDK Telegram 연동
- templates/shorts_template.json: 코너별 색상/TTS/트랜지션 설정
- scripts/download_fonts.py: NotoSansKR / 맑은고딕 자동 설치
- .gitignore: .claude/, 기획문서, 생성 미디어 파일 추가
- .env.example: 플레이스홀더 텍스트 (실제 값 없음)
- README: v3 아키텍처 전체 문서화 (설치/API키/상세설명/FAQ)
- requirements.txt: openai, pydub 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sinmb79
2026-03-25 18:15:07 +09:00
parent 6d6ba14e76
commit b54f8e198e
24 changed files with 4367 additions and 274 deletions

816
README.md
View File

@@ -1,94 +1,155 @@
# 블로그 자동 수익 엔진 (Blog Auto Revenue Engine)
# 블로그 자동 수익 엔진 v3
AI 기반 한국어 블로그 자동화 시스템.
트렌드 수집 → AI 글 작성 → 자동 발행 → 수익 링크 삽입 → 성과 분석까지 전 과정을 자동화합니다.
**The 4th Path — Independent Tech Media** | by [22B Labs](https://github.com/sinmb79)
> **Phase 1 목표:** Google Blogger 블로그 1개로 시작해 검색 자산 축적 + AdSense 승인
원고 하나를 AI로 작성하면 블로그, 인스타그램 카드, X 스레드, 유튜브 쇼츠, 주간 뉴스레터 — **5개 포맷으로 자동 변환·배포**하는 1인 미디어 자동화 시스템입니다.
> Python 기반, Windows 미니PC 24시간 운영 최적화.
> Google Blogger + AdSense + 쿠팡 파트너스 + 멀티플랫폼 수익 구조.
---
## 목차
1. [시스템 구조](#시스템-구조)
2. [사전 준비](#사전-준비)
3. [설치 방법](#설치-방법)
4. [API 키 설정](#api-키-설정)
5. [Google OAuth 인증](#google-oauth-인증)
6. [실행하기](#실행하기)
7. [Telegram 명령어](#telegram-명령어)
8. [이미지 모드 선택](#이미지-모드-선택)
9. [콘텐츠 코너 구성](#콘텐츠-코너-구성)
10. [Phase 로드맵](#phase-로드맵)
11. [자주 묻는 질문](#자주-묻는-질문)
- [아키텍처](#아키텍처)
- [기능 개요](#기능-개요)
- [프로젝트 구조](#프로젝트-구조)
- [설치](#설치)
- [환경 변수 설정](#환경-변수-설정)
- [Google OAuth 인증](#google-oauth-인증)
- [실행 방법](#실행-방법)
- [봇 상세 설명](#봇-상세-설명)
- [변환 엔진](#변환-엔진-layer-2)
- [배포 엔진](#배포-엔진-layer-3)
- [콘텐츠 코너](#콘텐츠-코너)
- [Telegram 명령어](#telegram-명령어)
- [OpenClaw AI 에이전트 연동](#openclaw-ai-에이전트-연동)
- [배포 스케줄](#배포-스케줄)
- [Phase 현황](#phase-현황)
- [자주 묻는 질문](#자주-묻는-질문)
- [기여 가이드](#기여-가이드)
- [라이선스](#라이선스)
---
## 시스템 구조
## 아키텍처
```
봇 레이어 (Python) AI 레이어 (OpenClaw)
───────────────── ────────────────────
수집봇 blog-writer 에이전트
└─ 트렌드 수집 └─ 글감 → 완성 글 작성
└─ 품질 점수 계산
└─ 폐기 규칙 적용
발행봇 ── 링크봇 ── 이미지봇
└─ 안전장치 └─ 만평 이미지
└─ Blogger 발행
└─ Search Console
분석봇 → Telegram 리포트
스케줄러 → 모든 봇 시간 관리
┌─────────────────────────────────────────────────────────────┐
│ LAYER 1 — AI 콘텐츠 생성 │
│ OpenClaw (GPT / Claude) → Blogger-ready HTML 원고 1개 │
└───────────────────────────┬─────────────────────────────────┘
│ article dict
┌───────────────────────────▼─────────────────────────────────┐
│ LAYER 2 — 변환 엔진 (Python, AI 없음)
│ │
│ blog_converter card_converter thread_converter │
HTML+Schema.org 1080×1080 카드 X 스레드 280자 │
│ │
shorts_converter newsletter_converter │
│ TTS+ffmpeg 쇼츠 영상 주간 HTML 뉴스레터
└───────────────────────────┬─────────────────────────────────┘
│ 5개 포맷
┌───────────────────────────▼─────────────────────────────────┐
│ LAYER 3 — 배포 엔진 (Python, AI 없음) │
│ Blogger Instagram X(Twitter) TikTok YouTube │
└───────────────────────────┬─────────────────────────────────┘
│ 지표
┌───────────────────────────▼─────────────────────────────────┐
│ LAYER 4 — 분석 + 피드백 │
│ Google Analytics · Search Console · Telegram 리포트 │
└─────────────────────────────────────────────────────────────┘
```
### 파일 구조
---
## 기능 개요
| 기능 | 설명 | Phase |
|------|------|-------|
| 트렌드 수집 | PyTrends + RSS 멀티소스, 품질 점수 70점 미만 자동 폐기 | 1A ✅ |
| AI 글 작성 | OpenClaw 에이전트 → Blogger-ready HTML 직접 출력 | 1A ✅ |
| 블로그 발행 | Blogger API + Schema.org JSON-LD + AdSense 플레이스홀더 | 1A ✅ |
| 쿠팡 파트너스 | 키워드 자동 링크 삽입 | 1A ✅ |
| 인스타 카드 | Pillow 1080×1080 카드 이미지 생성 + Instagram Graph API | 1B ✅ |
| X 스레드 | 280자 자동 분할 + X API v2 순차 게시 | 1B ✅ |
| 유튜브 쇼츠 | TTS + Pillow 슬라이드 + ffmpeg 영상 합성 + YouTube API | 2 ✅ |
| TikTok | TikTok Content Posting API v2 | 2 ✅ |
| 주간 뉴스레터 | 주간 HTML 뉴스레터 자동 생성 | 1A ✅ |
| 분석봇 | GA4 + Search Console + Telegram 일간/주간 리포트 | 1A ✅ |
| Telegram 제어 | 명령어 + Claude API 자연어 폴백 | 1A ✅ |
---
## 프로젝트 구조
```
blog-writer/
├── bots/
│ ├── collector_bot.py ← 수집봇 (Google Trends, GitHub, HN, RSS)
│ ├── publisher_bot.py ← 발행봇 (Blogger API + 안전장치)
│ ├── linker_bot.py ← 링크봇 (쿠팡 파트너스)
│ ├── analytics_bot.py ← 분석봇 (5대 핵심 지표)
│ ├── image_bot.py ← 이미지봇 (만평 3가지 모드)
│ ├── scheduler.py ← 스케줄러 + Telegram 봇
── article_parser.py ← OpenClaw 출력 파서
├── config/
│ ├── blogs.json ← 블로그 ID 설정
├── schedule.json ← 발행 시간표
│ ├── sources.json ← 수집 소스 목록
│ ├── affiliate_links.json← 어필리에이트 링크 DB
│ ├── quality_rules.json ← 품질 점수 기준
└── safety_keywords.json← 안전장치 키워드
├── data/ ← 런타임 데이터 (gitignore)
├── bots/ # 핵심 봇 모듈
│ ├── collector_bot.py # 트렌드 수집 + 품질 필터
│ ├── publisher_bot.py # Blogger API 발행
│ ├── linker_bot.py # 쿠팡 파트너스 링크 삽입
│ ├── analytics_bot.py # 성과 수집 + 리포트
│ ├── image_bot.py # 만평 이미지 (manual/request/auto)
── article_parser.py # 원고 포맷 파서
│ ├── remote_claude.py # Claude Agent SDK Telegram 연동
│ ├── scheduler.py # APScheduler + Telegram 리스너
│ ├── converters/ # LAYER 2 — 변환 엔진
│ ├── blog_converter.py # HTML 정제 + Schema.org + AdSense
│ ├── card_converter.py # 인스타 카드 이미지 (Pillow)
│ ├── thread_converter.py # X 스레드 280자 분할
├── newsletter_converter.py# 주간 뉴스레터 HTML
│ │ └── shorts_converter.py # 쇼츠 영상 (TTS + ffmpeg)
│ │
│ └── distributors/ # LAYER 3 — 배포 엔진
│ ├── image_host.py # ImgBB 업로드 / 로컬 HTTP 서버
│ ├── instagram_bot.py # Instagram Graph API
│ ├── x_bot.py # X API v2 (OAuth1)
│ ├── tiktok_bot.py # TikTok Content Posting API v2
│ └── youtube_bot.py # YouTube Data API v3
├── config/ # 설정 파일 (비밀값 없음)
│ ├── platforms.json # 플랫폼 활성화 여부
│ ├── schedule.json # 스케줄 시간 설정
│ ├── quality_rules.json # 품질 필터 규칙
│ ├── safety_keywords.json # 안전 키워드 목록
│ ├── sources.json # RSS 피드 + 트렌드 소스
│ ├── blogs.json # 블로그 설정
│ └── affiliate_links.json # 제휴 링크 목록
├── templates/
│ └── shorts_template.json # 쇼츠 코너별 설정 (색상/TTS/트랜지션)
├── scripts/
│ ├── get_token.py ← Google OAuth 토큰 발급
── setup.bat ← Windows 설치 스크립트
├── .env.example ← 환경변수 템플릿
└── requirements.txt
│ ├── setup.bat # Windows 최초 설치 스크립트
── get_token.py # Google OAuth 토큰 발급
│ └── download_fonts.py # NotoSansKR / 맑은고딕 설치
├── assets/
│ └── fonts/ # .ttf 파일 (scripts/download_fonts.py로 설치)
├── data/ # 런타임 데이터 (.gitignore)
│ ├── originals/ # AI 생성 원고
│ ├── outputs/ # 변환 결과물 (HTML/PNG/MP4/JSON)
│ └── ...
├── logs/ # 로그 (.gitignore)
├── .env.example # 환경 변수 템플릿
├── requirements.txt
└── README.md
```
---
## 사전 준비
## 설치
### 필수
- **Python 3.11 이상** — [python.org](https://www.python.org/downloads/)
- **Git** — [git-scm.com](https://git-scm.com/)
- **Google 계정** — Blogger 블로그 운영용
- **Telegram 계정** — 봇 알림 수신용
- **OpenClaw** — AI 글 작성 에이전트 (ChatGPT Pro 구독 필요)
### 사전 요구사항
### 선택
- **쿠팡 파트너스 계정** — 링크 수익화용
- **OpenAI API Key** — 이미지 자동 생성 모드 사용 시
---
## 설치 방법
- **Python 3.10 이상** — [python.org](https://www.python.org/downloads/)
- **ffmpeg** — 쇼츠 영상 생성 필수. [ffmpeg.org](https://ffmpeg.org/download.html)에서 다운로드 후 PATH 추가 또는 `.env``FFMPEG_PATH` 지정
- Windows 미니PC 권장 (24시간 운영), macOS/Linux도 동작
### 1. 저장소 클론
@@ -97,89 +158,117 @@ git clone https://github.com/sinmb79/blog-writer.git
cd blog-writer
```
### 2. 설치 스크립트 실행 (Windows)
탐색기에서 `scripts\setup.bat` 더블클릭 또는:
```cmd
scripts\setup.bat
```
스크립트가 자동으로 처리하는 것:
- Python 가상환경(`venv`) 생성
- 패키지 설치 (`requirements.txt`)
- `.env` 파일 생성 (`.env.example` 복사)
- `data/`, `logs/` 폴더 생성
- Windows 작업 스케줄러에 자동 시작 등록
### 3. 수동 설치 (선택)
### 2. 가상환경 + 패키지 설치
```bash
# Windows — 자동 설치 (권장)
scripts\setup.bat
# 수동 설치
python -m venv venv
venv\Scripts\activate # Windows
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
pip install -r requirements.txt
copy .env.example .env
```
`setup.bat`이 처리하는 것:
- Python 가상환경 생성
- 패키지 설치
- `.env` 파일 생성 (`.env.example` 복사)
- `data/`, `logs/` 폴더 생성
- Windows 작업 스케줄러 자동 시작 등록
### 3. 폰트 설치
카드 이미지·쇼츠 영상의 한글 렌더링에 필요합니다.
```bash
python scripts/download_fonts.py
```
Windows: `맑은고딕(malgunbd.ttf)``assets/fonts/`에 자동 복사
macOS/Linux: NotoSansKR을 GitHub에서 다운로드
### 4. 환경 변수 설정
```bash
cp .env.example .env
# .env 파일을 열어 값 입력
```
---
## API 키 설정
## 환경 변수 설정
`.env` 파일을 열고 아래 항목을 입력합니다.
`.env.example`을 복사해 `.env`로 저장 후 아래 값을 채웁니다.
`.env` 파일은 절대 커밋하지 마세요 — `.gitignore`에 포함되어 있습니다.
### Phase 1A — 필수
| 변수 | 설명 | 발급처 |
|------|------|--------|
| `GOOGLE_CLIENT_ID` | OAuth 클라이언트 ID | [Google Cloud Console](https://console.cloud.google.com/) |
| `GOOGLE_CLIENT_SECRET` | OAuth 클라이언트 시크릿 | Google Cloud Console |
| `GOOGLE_REFRESH_TOKEN` | `scripts/get_token.py` 실행 후 자동 저장 | — |
| `BLOG_MAIN_ID` | Blogger 블로그 ID | Blogger 대시보드 URL |
| `TELEGRAM_BOT_TOKEN` | Telegram 봇 토큰 | [@BotFather](https://t.me/BotFather) |
| `TELEGRAM_CHAT_ID` | 내 Telegram 채팅 ID | [@userinfobot](https://t.me/userinfobot) |
| `COUPANG_ACCESS_KEY` | 쿠팡 파트너스 액세스 키 | [쿠팡 파트너스](https://partners.coupang.com/) |
| `COUPANG_SECRET_KEY` | 쿠팡 파트너스 시크릿 키 | 쿠팡 파트너스 |
**BLOG_MAIN_ID 확인 방법**
Blogger 관리자 → 블로그 선택 → 주소창:
```
https://www.blogger.com/blog/posts/3856391132195789013
↑ 이 숫자
```
### Phase 1B — 인스타그램 / X
| 변수 | 설명 | 발급처 |
|------|------|--------|
| `INSTAGRAM_ACCESS_TOKEN` | Instagram Graph API 장기 토큰 | [Facebook Developers](https://developers.facebook.com/) |
| `INSTAGRAM_ACCOUNT_ID` | Instagram 비즈니스 계정 ID | Facebook Developers |
| `X_API_KEY` | X API 키 | [X Developer Portal](https://developer.twitter.com/) |
| `X_API_SECRET` | X API 시크릿 | X Developer Portal |
| `X_ACCESS_TOKEN` | X 액세스 토큰 | X Developer Portal |
| `X_ACCESS_SECRET` | X 액세스 시크릿 | X Developer Portal |
| `IMGBB_API_KEY` | 이미지 공개 URL 변환 (무료) | [ImgBB](https://api.imgbb.com/) |
### Phase 2 — 쇼츠 / TikTok / YouTube
| 변수 | 설명 | 발급처 |
|------|------|--------|
| `GOOGLE_TTS_API_KEY` | Google Cloud TTS REST API | [Google Cloud Console](https://console.cloud.google.com/) |
| `FFMPEG_PATH` | ffmpeg 경로 (PATH 미등록 시만) | — |
| `OPENAI_API_KEY` | DALL-E 3 배경 이미지 (선택) | [OpenAI](https://platform.openai.com/) |
| `TIKTOK_ACCESS_TOKEN` | TikTok Content Posting API | [TikTok Developers](https://developers.tiktok.com/) |
| `TIKTOK_OPEN_ID` | TikTok 사용자 Open ID | TikTok Developers |
| `YOUTUBE_CHANNEL_ID` | YouTube 채널 ID | YouTube Studio |
| `ANTHROPIC_API_KEY` | Telegram 자연어 명령 처리 | [Anthropic Console](https://console.anthropic.com/) |
### 이미지 모드 선택
```env
# ─── Google (필수) ───────────────────────────────────
GOOGLE_CLIENT_ID= # Google Cloud Console에서 발급
GOOGLE_CLIENT_SECRET= # Google Cloud Console에서 발급
GOOGLE_REFRESH_TOKEN= # scripts/get_token.py 실행 후 입력
BLOG_MAIN_ID= # Blogger 대시보드 URL에서 확인
# ─── 쿠팡 파트너스 (선택, 링크 수익화) ────────────────
COUPANG_ACCESS_KEY=
COUPANG_SECRET_KEY=
# ─── Telegram (필수, 알림 수신) ──────────────────────
TELEGRAM_BOT_TOKEN= # @BotFather에서 발급
TELEGRAM_CHAT_ID= # @userinfobot에서 확인
# ─── 이미지 모드 ─────────────────────────────────────
IMAGE_MODE=manual # manual | request | auto
# ─── Search Console (선택) ───────────────────────────
BLOG_SITE_URL= # 예: https://your-blog.blogspot.com/
# ─── OpenAI (auto 모드만 필요) ───────────────────────
OPENAI_API_KEY=
IMAGE_MODE=manual # (기본) 발행 시 Telegram으로 프롬프트 전송
IMAGE_MODE=request # 매주 월요일 프롬프트 목록 일괄 전송
IMAGE_MODE=auto # DALL-E 3 자동 생성 (OPENAI_API_KEY 필요)
```
### BLOG_MAIN_ID 확인 방법
Blogger 관리자 페이지(blogger.com)에서 블로그를 선택한 뒤 브라우저 주소창을 확인합니다:
```
https://www.blogger.com/blog/posts/XXXXXXXXXXXXXXXXXX
↑ 이 숫자가 BLOG_MAIN_ID
```
### Telegram 설정 방법
1. Telegram에서 `@BotFather` 검색 → `/newbot` 명령 → 봇 생성 → **Token** 복사
2. 생성한 봇과 대화 시작 → `@userinfobot`에 메시지 → **Chat ID** 확인
---
## Google OAuth 인증
### 1. Google Cloud Console 설정
1. [console.cloud.google.com](https://console.cloud.google.com/) 접속
2. 새 프로젝트 생성
3. **API 및 서비스 → 라이브러리** 에서 아래 두 API 활성화:
1. [console.cloud.google.com](https://console.cloud.google.com/) → 새 프로젝트 생성
2. **API 및 서비스 → 라이브러리** 에서 아래 API 활성화:
- `Blogger API v3`
- `Google Search Console API`
4. **사용자 인증 정보 → OAuth 클라이언트 ID 만들기**
- `YouTube Data API v3` (Phase 2)
3. **사용자 인증 정보 → OAuth 클라이언트 ID 만들기**
- 애플리케이션 유형: **데스크톱 앱**
5. `credentials.json` 다운로드 → 프로젝트 루트(`blog-writer/`)에 저장
4. `credentials.json` 다운로드 → 프로젝트 루트에 저장
### 2. 토큰 발급
@@ -188,175 +277,436 @@ venv\Scripts\activate
python scripts\get_token.py
```
브라우저가 열리면 Google 계정으로 로그인 → 권한 허용
터미널에 출력된 `REFRESH_TOKEN` 값을 `.env` `GOOGLE_REFRESH_TOKEN`에 붙여넣기
브라우저에서 Google 계정 인증 → `token.json` 자동 저장.
`credentials.json``token.json` `.gitignore`에 포함 — 절대 커밋하지 마세요.
---
## 실행하기
## 실행 방법
### 스케줄러 시작 (메인 프로세스)
### 스케줄러 시작 (권장)
```bash
venv\Scripts\activate
python bots\scheduler.py
```
### 각 봇 단독 테스트
백그라운드 실행 (Windows):
```bash
# 수집봇 테스트 (글감 수집)
python bots\collector_bot.py
# 분석봇 테스트 (일일 리포트)
python bots\analytics_bot.py
# 분석봇 주간 리포트
python bots\analytics_bot.py weekly
# 이미지 프롬프트 배치 전송 (request 모드)
python bots\image_bot.py batch
pythonw bots\scheduler.py
```
### 자동 시작 확인 (Windows)
Windows 작업 스케줄러를 통해 PC 시작 시 자동 실행되도록 `setup.bat`이 등록합니다.
작업 스케줄러(`taskschd.msc`)에서 **BlogEngine** 작업이 등록되어 있으면 PC 시작 시 자동 실행됩니다.
### 개별 봇 단독 실행
```bash
python bots\collector_bot.py # 트렌드 수집
python bots\publisher_bot.py # 블로그 발행
python bots\analytics_bot.py # 일간 리포트
python bots\analytics_bot.py weekly # 주간 리포트
python bots\image_bot.py batch # 이미지 프롬프트 배치 전송
# 변환 엔진
python bots\converters\blog_converter.py
python bots\converters\card_converter.py
python bots\converters\shorts_converter.py
```
---
## 일일 자동 플로우
## 봇 상세 설명
| 시간 | 작업 |
### `collector_bot.py` — 트렌드 수집봇
Google Trends (PyTrends) + RSS 피드 (`config/sources.json`)에서 글감을 수집하고 품질 점수를 계산합니다.
**품질 점수 (0100):**
- 트렌드 강도, 경쟁 기사 수, 키워드 밀도 반영
- **70점 미만 자동 폐기**
- 75점 미만 또는 위험 키워드 감지 시 Telegram 수동 검토 요청
**출력:** `data/collected/{date}_{slug}.json`
### `publisher_bot.py` — 발행봇
- HTML 본문 감지: AI가 HTML을 직접 출력한 경우 변환 없이 Blogger에 발행
- Schema.org `Article` JSON-LD 삽입
- Google Search Console URL 즉시 색인 요청
- 하루 최대 발행 수 제한, 중복 발행 방지
### `linker_bot.py` — 쿠팡 파트너스 링크봇
`config/affiliate_links.json`의 키워드를 HTML 본문에서 찾아 파트너스 링크로 자동 교체.
같은 키워드는 최대 2회까지만 처리합니다.
### `analytics_bot.py` — 분석봇
- Google Analytics Data API v1 (GA4) + Search Console API
- 매일 22:00 수집 → Telegram 일간 리포트
- 매주 일요일 22:30 주간 종합 리포트
### `image_bot.py` — 이미지봇
| 모드 | 동작 |
|------|------|
| 07:00 | 수집봇 — 트렌드 수집 + 품질 점수 계산 + 폐기 필터링 |
| 08:00 | AI 글 작성 트리거 (OpenClaw 서브에이전트) |
| 09:00 | 발행봇 — 첫 번째 글 발행 |
| 12:00 | 발행봇 — 두 번째 글 발행 |
| 15:00 | 발행봇 — 세 번째 글 (선택) |
| 22:00 | 분석봇 — 일일 리포트 → Telegram 전송 |
| 매주 일요일 22:30 | 분석봇 — 주간 리포트 |
| 매주 월요일 10:00 | 이미지봇 — 프롬프트 배치 전송 (request 모드) |
| `manual` | 발행 시 DALL-E 프롬프트를 Telegram 전송. 직접 생성 후 저장. |
| `request` | 매주 월요일 프롬프트 목록 전송. 일괄 생성 후 개별 전송. |
| `auto` | DALL-E 3 API 자동 생성. `OPENAI_API_KEY` 필요, 비용 발생. |
### `article_parser.py` — 원고 파서
OpenClaw AI가 출력하는 구조화된 원고를 파싱합니다:
```
---TITLE--- 글 제목
---META--- 검색 설명 150자
---SLUG--- URL 슬러그
---TAGS--- 태그 목록
---CORNER--- 코너명
---BODY--- Blogger-ready HTML 본문
---KEY_POINTS--- 핵심 3줄 (각 30자 이내, SNS/TTS용)
---COUPANG_KEYWORDS--- 쿠팡 검색 키워드
---SOURCES--- 출처 URL 목록
---DISCLAIMER--- 면책 문구
```
### `remote_claude.py` — Claude Agent SDK 연동
Telegram 자연어 명령을 Claude Agent SDK로 처리합니다.
코드 생성·수정·실행까지 가능한 자율 에이전트 인터페이스입니다.
---
## Telegram 명령어
## 변환 엔진 (LAYER 2)
### 텍스트 명령 (키보드로 입력)
### `blog_converter.py`
| 명령 | 설명 |
|------|------|
| `발행 중단` | 자동 발행 일시 중지 |
| `발행 재개` | 자동 발행 재개 |
| `오늘 수집된 글감 보여줘` | 오늘 수집된 글감 목록 |
| `대기 중인 글 보여줘` | 수동 검토 대기 글 목록 |
| `이번 주 리포트` | 주간 리포트 즉시 생성 |
| `이미지 목록` | 이미지 제작 현황 |
```
입력: article dict (body = HTML 또는 Markdown)
출력: data/outputs/{date}_{slug}_blog.html
```
### 슬래시 명령
- **HTML 자동 감지**: AI가 HTML을 직접 출력한 경우 마크다운 변환을 건너뜀
- Schema.org `Article` JSON-LD 삽입
- AdSense 플레이스홀더 삽입 (2번째 H2 뒤, 결론 H2 앞)
- 쿠팡 파트너스 링크봇 호출
| 명령 | 설명 |
|------|------|
| `/status` | 봇 상태 + 이미지 모드 확인 |
| `/approve [번호]` | 수동 검토 글 승인 후 발행 |
| `/reject [번호]` | 수동 검토 글 거부 |
| `/images` | 이미지 제작 대기/진행/완료 현황 |
| `/imgpick [번호]` | 해당 번호 이미지 프롬프트 받기 |
| `/imgbatch` | 프롬프트 배치 수동 전송 |
| `/imgcancel` | 이미지 대기 상태 취소 |
### `card_converter.py`
```
입력: article dict
출력: data/outputs/{date}_{slug}_card.png (1080×1080)
```
Pillow로 인스타그램 카드 이미지를 생성합니다:
```
┌─────────────────────────┐
│ ████ 금색 상단 바 │
│ │
│ [코너 배지] │
│ │
│ 글 제목 │
│ │
│ • 핵심 포인트 1 │
│ • 핵심 포인트 2 │
│ • 핵심 포인트 3 │
│ │
│ ████ 금색 하단 바 (URL) │
└─────────────────────────┘
```
코너별 배지 색상: 쉬운세상=파랑, 숨은보물=초록, 바이브리포트=보라, 팩트체크=빨강, 한컷=노랑
### `thread_converter.py`
```
입력: article dict
출력: data/outputs/{date}_{slug}_thread.json
```
- Tweet 1: 제목 + 코너 해시태그
- Tweet 24: 번호 매긴 핵심 포인트
- 마지막 Tweet: 블로그 URL + CTA
### `newsletter_converter.py`
```python
generate_weekly(articles: list[dict], urls: list[str] = None) -> str
```
주간 기사 목록으로 HTML 뉴스레터를 생성합니다.
**출력:** `data/outputs/weekly_{date}_newsletter.html`
### `shorts_converter.py`
뉴스 앵커 형식의 세로형 쇼츠 영상을 생성합니다 (1080×1920, 30fps).
**파이프라인:**
```
1. DALL-E 3 배경 이미지 생성 (옵션, 없으면 단색)
2. Pillow 슬라이드 합성
인트로 → 헤드라인 → 포인트1 → 포인트2 → 포인트3 → 데이터(선택) → 아웃트로
3. Google Cloud TTS (ko-KR-Wavenet-A) → gTTS 폴백
4. ffmpeg zoompan — Ken Burns 효과로 슬라이드별 MP4 클립 생성
5. ffmpeg xfade — 코너별 트랜지션으로 클립 연결
6. BGM 믹싱 (assets/bgm.mp3, 볼륨 8%)
7. SRT 자막 burn-in (흰 텍스트 + 반투명 검정 박스)
출력: data/outputs/{date}_{slug}_shorts.mp4
```
**코너별 설정** (`templates/shorts_template.json`):
| 코너 | 색상 | TTS 속도 | 트랜지션 | 특이사항 |
|------|------|----------|---------|---------|
| 쉬운세상 | 보라 `#7c3aed` | 1.0x | fade | — |
| 숨은보물 | 블루 `#1d6fb0` | 1.05x | slideleft | — |
| 바이브리포트 | 코럴 `#d85a30` | 1.1x | slideleft | — |
| 팩트체크 | 레드 `#bf3a3a` | 1.0x | fade | 데이터 카드 강제 |
| 한컷 | 골드 `#8a7a2e` | 1.0x | fade | 최대 20초 |
---
## 이미지 모드 선택
## 배포 엔진 (LAYER 3)
`.env``IMAGE_MODE` 값으로 선택합니다.
### `image_host.py`
### `manual` (기본)
한컷 코너 글 발행 시점에 프롬프트 1개를 Telegram으로 전송.
사용자가 직접 이미지를 생성해 `data/images/` 에 파일 저장.
Instagram API는 공개 URL 이미지만 허용하므로 로컬 파일을 업로드합니다:
- **ImgBB API** (기본): 무료 이미지 호스팅, `IMGBB_API_KEY` 필요
- **로컬 HTTP 서버**: 개발/테스트용, `LOCAL_IMAGE_SERVER=true`
### `request` (권장)
매주 월요일 10:00 대기 중인 프롬프트 목록을 Telegram으로 일괄 전송.
### `instagram_bot.py`
**사용 흐름:**
1. 봇이 프롬프트 목록 전송 (또는 `/imgbatch` 수동 트리거)
2. `/imgpick 3` — 3번 프롬프트 전체 내용 수신
3. 프롬프트 복사 → Midjourney / DALL-E 웹 / Stable Diffusion 등에 붙여넣기
4. 생성된 이미지를 Telegram으로 전송 (캡션에 `#3` 입력 또는 `/imgpick` 후 바로 전송)
5. 봇이 자동 저장 + 완료 처리
Instagram Graph API v19.0 흐름:
1. `POST /media` — 미디어 컨테이너 생성
2. `GET /media/{id}``FINISHED` 상태까지 폴링 (최대 2분)
3. `POST /media_publish` — 컨테이너 발행
### `auto`
OpenAI DALL-E 3 API를 직접 호출해 자동 생성.
`OPENAI_API_KEY` 필요. 이미지당 $0.040.08 비용 발생 (ChatGPT Pro 구독과 별도).
### `x_bot.py`
X API v2 + OAuth1 (`requests_oauthlib`):
- 이전 트윗 ID를 `reply_to_id`로 넘겨 스레드 구성
- 각 트윗 사이 1초 딜레이로 순서 보장
### `tiktok_bot.py`
TikTok Content Posting API v2 (Direct Post):
1. `POST /v2/post/publish/video/init/` — 업로드 URL + `publish_id` 수령
2. 청크 업로드
3. `POST /v2/post/publish/status/fetch/` — 발행 완료 폴링
### `youtube_bot.py`
YouTube Data API v3:
- 기존 `token.json` Google OAuth 재사용 (별도 인증 불필요)
- 제목 끝에 `#Shorts` 자동 추가
- `google-resumable-media`로 대용량 파일 청크 업로드
---
## 콘텐츠 코너 구성
## 콘텐츠 코너
| 코너 | 컨셉 | 발행 빈도 |
|------|------|-----------|
| **쉬운 세상** | AI/테크를 누구나 따라할 수 있게 | 주 23회 |
| **숨은 보물** | 모르면 손해인 무료 도구 발굴 | 주 23회 |
| **바이브 리포트** | 비개발자가 AI로 만든 실제 사례 | 주 12회 |
| **팩트체크** | 과대광고/거짓 주장 검증 (수동 승인 필수) | 주 1회 이하 |
| **한 ** | AI/테크 이슈 만평 | 주 1회 |
| 코너 | 성격 | 글 길이 | 안전장치 |
|------|------|---------|---------|
| **쉬운세상** | 복잡한 이슈를 쉽게 해설 | 1,5002,000자 | 자동 발행 |
| **숨은보물** | 유용하지만 덜 알려진 정보 | 1,5002,000자 | 자동 발행 |
| **바이브리포트** | 트렌드·문화 분석 | 1,5002,500자 | 자동 발행 |
| **팩트체크** | [사실]/[의견]/[추정] 명시 검증 | 2,0002,500자 | **수동 승인 필수** |
| **한컷** | 시사 만평 + 짧은 코멘트 | 300500자 | 자동 발행 |
### 안전장치 (자동 발행 차단 조건)
아래 조건에 해당하면 자동 발행 대신 Telegram으로 수동 검토 요청:
- 팩트체크 코너 글 전체
- 암호화폐/투자/법률 관련 위험 키워드 감지
**자동 발행 차단 조건 (Telegram 수동 검토):**
- 팩트체크 코너 전체
- 암호화폐/투자/법률 위험 키워드 감지
- 출처 2개 미만
- 품질 점수 75점 미만
---
## OpenClaw 서브에이전트 설정
## Telegram 명령어
`~/.openclaw/` 디렉토리에 아래 파일을 배치합니다:
스케줄러 실행 중 Telegram 봇에 명령을 보낼 수 있습니다.
### 슬래시 명령
| 명령 | 설명 |
|------|------|
| `/start` | 봇 소개 |
| `/status` | 스케줄러 상태 + 오늘 발행 수 |
| `/collect` | 즉시 트렌드 수집 |
| `/publish` | 즉시 블로그 발행 |
| `/convert` | 즉시 변환 파이프라인 실행 |
| `/report` | 즉시 분석 리포트 |
| `/pause` | 자동 스케줄 일시 중지 |
| `/resume` | 자동 스케줄 재개 |
| `/approve [번호]` | 수동 검토 글 승인 후 발행 |
| `/reject [번호]` | 수동 검토 글 거부 |
| `/images` | 이미지 제작 현황 |
| `/imgbatch` | 이미지 프롬프트 배치 전송 |
| `/help` | 명령어 목록 |
### 자연어 명령 (`ANTHROPIC_API_KEY` 설정 시)
```
~/.openclaw/
├── agents/
│ ├── main/AGENTS.md ← 에이전트 관리 규칙
│ └── blog-writer/SOUL.md ← 글쓰기 에이전트 설정
└── workspace-blog-writer/
├── personas/tech_insider.md ← 테크인사이더 페르소나
├── corners/ ← 5개 코너 설정 파일
└── templates/output_format.md ← 출력 포맷 템플릿
"오늘 발행된 글 목록 보여줘"
"쇼츠 변환 다시 실행해줘"
"이번 주 조회수 상위 3개 알려줘"
```
이 파일들은 설치 시 `~/.openclaw/` 에 수동으로 복사해야 합니다.
(OpenClaw 설정 완료 후 `scheduler.py``_call_openclaw()` 함수를 실제 호출 코드로 교체)
---
## Phase 로드맵
## OpenClaw AI 에이전트 연동
| Phase | 기간 | 목표 | 예상 수익 |
|-------|------|------|----------|
| **1** | Month 13 | 블로그 1개, 시스템 검증, AdSense 승인 | 05만원/월 |
| **2** | Month 35 | 블로그 2개, 쿠팡 수익 집중 | 520만원/월 |
| **3** | Month 58 | 34개 블로그, 어필리에이트 추가 | 1050만원/월 |
| **4** | Month 8+ | 영문 블로그, 글로벌 확장 | 30100만원+/월 |
이 프로젝트는 [OpenClaw](https://openclaw.ai) AI 에이전트와 함께 사용하도록 설계되었습니다.
**에이전트 설정 파일 위치:**
```
~/.openclaw/agents/blog-writer/SOUL.md
역할, 글쓰기 원칙, Blogger-ready HTML 출력 조건
~/.openclaw/workspace-blog-writer/templates/output_format.md
원고 출력 포맷 (섹션 구조 정의)
```
**AI 원고 출력 포맷** (`output_format.md` 기반):
```
---TITLE--- 제목 (SEO 키워드 포함, 클릭베이트 없음)
---META--- 검색 설명 150자 이내
---SLUG--- URL 슬러그 (영문 소문자, 하이픈)
---TAGS--- 태그 쉼표 구분
---CORNER--- 코너명
---BODY--- Blogger-ready HTML 본문 (마크다운 금지)
---KEY_POINTS--- 핵심 3줄 (각 30자 이내, SNS/TTS용)
---COUPANG_KEYWORDS--- 쿠팡 검색 키워드
---SOURCES--- 출처 URL 목록
---DISCLAIMER--- 면책 문구 (팩트체크 필수)
```
**HTML 본문 필수 구성요소:**
- `<style>` 블록 맨 앞 (`.post-title` 숨김 포함)
- eyebrow 배지 · h1 제목 + 부제 · 메타 정보
- 섹션 트래커 (소문자 영문 앵커) · h3 소제목
- pull quote · 데이터 카드/그리드 · balance-box (반론)
- 출처 cite · 클로징 박스 · 태그 목록
- 저자: `22B Labs · The 4th Path`
OpenClaw 없이도 동작합니다 — 위 포맷에 맞춰 `data/originals/`에 파일을 직접 넣으면 파이프라인이 실행됩니다.
---
## 배포 스케줄
스케줄러 실행 시 매일 자동으로 실행됩니다 (`config/schedule.json`에서 시간 변경 가능):
| 시간 | 작업 |
|------|------|
| 07:00 | 트렌드 수집 (collector_bot) |
| 08:00 | AI 글 작성 트리거 (OpenClaw) |
| 08:30 | 변환 파이프라인 (5개 포맷 동시 생성) |
| 09:00 | 블로그 발행 (Blogger) |
| 10:00 | 인스타그램 카드 게시 |
| 11:00 | X 스레드 게시 |
| 18:00 | TikTok 쇼츠 업로드 |
| 20:00 | YouTube 쇼츠 업로드 |
| 22:00 | 일간 분석 리포트 (Telegram) |
| 일요일 22:30 | 주간 뉴스레터 + 종합 리포트 |
---
## Phase 현황
### Phase 1A — 완료 ✅
모든 핵심 봇 구현 완료. 블로그 자동 수집→작성→발행 파이프라인 작동.
### Phase 1B — 코드 완료 ✅, API 키 설정 필요 ⚙️
- [ ] `IMGBB_API_KEY` 발급 ([api.imgbb.com](https://api.imgbb.com/))
- [ ] Facebook Developer App에서 `INSTAGRAM_ACCESS_TOKEN` / `INSTAGRAM_ACCOUNT_ID` 발급
- [ ] X Developer Portal에서 API 키 4종 발급
### Phase 2 — 코드 완료 ✅, 환경 설정 필요 ⚙️
- [ ] `ffmpeg` 설치 및 PATH 등록
- [ ] `GOOGLE_TTS_API_KEY` 발급 (또는 `gTTS` 무료 사용)
- [ ] `TIKTOK_ACCESS_TOKEN` / `YOUTUBE_CHANNEL_ID` 발급
---
## 자주 묻는 질문
**Q. ChatGPT Pro 없이도 사용할 수 있나요?**
A. 봇 레이어(수집/발행/링크/분석)는 ChatGPT 없이 동작합니다. 글 작성(AI 레이어)만 OpenClaw + ChatGPT Pro를 사용합니다. 다른 LLM으로 교체하려면 `scheduler.py``_call_openclaw()` 함수를 수정하세요.
**Q. OpenClaw 없이도 사용할 수 있나요?**
A. 봇 레이어(수집/변환/발행/분석)는 완전히 독립적으로 동작합니다. `data/originals/`에 지정된 포맷으로 원고 파일을 직접 넣으면 파이프라인이 실행됩니다. 다른 AI(GPT API, Gemini 등)로 글을 생성한 후 넣어도 됩니다.
**Q. TTS 없이 쇼츠를 만들 수 있나요?**
A. `GOOGLE_TTS_API_KEY` 없이도 `gTTS`(무료)로 폴백됩니다. 품질은 낮지만 비용 없이 동작합니다. `requirements.txt``gTTS`가 포함되어 있습니다.
**Q. DALL-E 없이 쇼츠를 만들 수 있나요?**
A. `OPENAI_API_KEY`가 없으면 코너 색상 단색 배경으로 대체됩니다. 별도 조치 없이 자동으로 폴백됩니다.
**Q. Blogger 외 다른 플랫폼을 사용할 수 있나요?**
A. `publisher_bot.py``publish_to_blogger()` 함수를 교체하면 WordPress, 티스토리 등으로 변경 가능합니다.
A. `publisher_bot.py``publish_to_blogger()` 함수를 교체하면 WordPress REST API, 티스토리 등으로 변경 가능합니다.
**Q. Windows가 아닌 환경에서 사용하려면?**
A. `setup.bat` 대신 수동으로 venv 생성하고 패키지 설치하세요. `scheduler.py`는 크로스 플랫폼으로 동작합니다. Windows 작업 스케줄러 등록 부분만 Linux cron 또는 macOS launchd로 대체하세요.
A. `setup.bat` 대신 수동으로 venv 생성 패키지 설치, `scheduler.py`는 크로스 플랫폼 동작합니다. Windows 작업 스케줄러 등록 부분만 Linux cron 또는 macOS launchd로 대체하세요.
**Q. 수집봇이 아무것도 가져오지 못해요.**
A. `config/sources.json`의 RSS URL 유효한지 확인하세요. Google Trends는 간혹 요청 제한이 걸릴 수 있으며, 이 경우 `pytrends` 관련 로그를 확인하세요.
**Q. 수집봇이 글감을 못 가져와요.**
A. `config/sources.json`의 RSS URL 유효성을 확인하세요. Google Trends는 요청 제한이 걸릴 수 있습니다 — `logs/collector.log`에서 상세 오류를 확인하세요.
---
## 기여 가이드
PR과 이슈를 환영합니다.
### 로컬 개발 환경
```bash
git clone https://github.com/sinmb79/blog-writer.git
cd blog-writer
python -m venv venv && venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # 값 채우기
python scripts/download_fonts.py
```
### 브랜치 규칙
```
master — 안정 버전
feature/* — 새 기능
fix/* — 버그 수정
```
### 코드 스타일
- Python 3.10+, 타입 힌트 권장
- 모듈별 `logger = logging.getLogger(__name__)` 사용
- 환경 변수는 반드시 `.env`에서만 (`python-dotenv`)
- **비밀값 하드코딩 절대 금지**
### 보안 주의사항
- `.env`, `token.json`, `credentials.json``.gitignore`에 포함 — 절대 커밋하지 마세요
- PR 전 `git diff --staged`로 비밀값이 포함되지 않았는지 반드시 확인하세요
---
## 라이선스
MIT License — 자유롭게 사용, 수정, 배포 가능합니다.
MIT License — 자유롭게 사용·수정·배포 가능합니다.
상업적 이용 시 브랜드명 "The 4th Path"와 "22B Labs"는 제거해 주세요.
---
<p align="center">
<strong>The 4th Path</strong> · Independent Tech Media<br>
by <a href="https://github.com/sinmb79">22B Labs</a>
</p>