diff --git a/.env.example b/.env.example index e4cef9c..b0396e3 100644 --- a/.env.example +++ b/.env.example @@ -1,17 +1,77 @@ -GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com -GOOGLE_CLIENT_SECRET=your-google-client-secret +# ─── Google OAuth (필수) ───────────────────────────── +# Google Cloud Console > 사용자 인증 정보 > OAuth 클라이언트 ID에서 발급 +# https://console.cloud.google.com/ +GOOGLE_CLIENT_ID=your_google_oauth_client_id.apps.googleusercontent.com +GOOGLE_CLIENT_SECRET=your_google_oauth_client_secret +# scripts/get_token.py 실행 후 자동 저장됨 GOOGLE_REFRESH_TOKEN= -BLOG_MAIN_ID=your-blogger-blog-id +# Blogger 대시보드 URL에서 확인 (숫자 18자리) +BLOG_MAIN_ID=your_blogger_blog_id + +# ─── 쿠팡 파트너스 (선택) ───────────────────────────── +# https://partners.coupang.com/ 에서 발급 COUPANG_ACCESS_KEY= COUPANG_SECRET_KEY= -TELEGRAM_BOT_TOKEN=your-telegram-bot-token -TELEGRAM_CHAT_ID=your-telegram-chat-id -# 이미지 모드 선택 (manual | request | auto) + +# ─── Telegram (필수) ────────────────────────────────── +# @BotFather에서 /newbot 명령으로 생성 +TELEGRAM_BOT_TOKEN=your_telegram_bot_token +# @userinfobot에서 확인 +TELEGRAM_CHAT_ID=your_telegram_chat_id + +# ─── 이미지 모드 선택 ───────────────────────────────── # manual — 글 발행 시점에 프롬프트 1개를 Telegram으로 전송 (기본값) # request — 매주 월요일 프롬프트 목록 전송 → 직접 생성 후 Telegram으로 이미지 전송 # auto — OpenAI DALL-E API 자동 생성 (OPENAI_API_KEY 필요, 별도 비용 발생) IMAGE_MODE=manual -# auto 모드 사용 시에만 입력 + +# OpenAI (auto 모드 또는 쇼츠 배경 이미지 자동 생성 시 필요) +# https://platform.openai.com/api-keys OPENAI_API_KEY= + # 블로그 사이트 URL (Search Console 등록용) BLOG_SITE_URL= + +# ─── v3: 멀티플랫폼 배포 ────────────────────────────── + +# [Instagram Graph API] Phase 1B +# Facebook Developer App에서 발급 (비즈니스 계정 필요) +# https://developers.facebook.com/ +INSTAGRAM_ACCESS_TOKEN= +INSTAGRAM_ACCOUNT_ID= + +# [X(Twitter) API v2] Phase 1B +# X Developer Portal에서 발급 (Free Tier 이상) +# https://developer.twitter.com/ +X_API_KEY= +X_API_SECRET= +X_ACCESS_TOKEN= +X_ACCESS_SECRET= + +# [Anthropic API] Telegram 자연어 명령용 (선택) +# https://console.anthropic.com/ +ANTHROPIC_API_KEY= + +# ─── v3: 이미지 호스팅 ──────────────────────────────── +# ImgBB (무료, https://api.imgbb.com/ 에서 키 발급) +# 인스타그램 카드 이미지를 공개 URL로 변환하는 데 사용 +IMGBB_API_KEY= +# 로컬 테스트용 HTTP 서버 (true/false) +LOCAL_IMAGE_SERVER=false + +# ─── v3 Phase 2: 쇼츠 변환 ─────────────────────────── +# Google Cloud TTS REST API (https://cloud.google.com/text-to-speech) +# 없으면 gTTS(무료)로 자동 대체됨 +GOOGLE_TTS_API_KEY= +# ffmpeg 경로 (PATH에 등록되지 않은 경우) +# FFMPEG_PATH=C:/ffmpeg/bin/ffmpeg.exe + +# ─── v3 Phase 2: TikTok ─────────────────────────────── +# TikTok Developers (https://developers.tiktok.com/) +TIKTOK_ACCESS_TOKEN= +TIKTOK_OPEN_ID= + +# ─── v3 Phase 2: YouTube ────────────────────────────── +# YouTube Data API v3 (기존 Google Cloud 프로젝트에서 API 추가 활성화) +# YouTube Studio > 채널 > 고급 설정에서 채널 ID 확인 +YOUTUBE_CHANNEL_ID= diff --git a/.gitignore b/.gitignore index b52b257..df68c0e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,21 @@ .env token.json credentials.json +service_account*.json +*_secret*.json +*_key*.json + +# Claude Code 내부 설정 +.claude/ + +# 내부 기획 문서 (비공개) +blog-engine-final-masterplan-v3.txt + +# 생성된 미디어 파일 +data/outputs/ +assets/bgm* +assets/fonts/*.ttf +assets/fonts/*.otf # Python venv/ diff --git a/README.md b/README.md index dbb1fea..cdd0432 100644 --- a/README.md +++ b/README.md @@ -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`)에서 글감을 수집하고 품질 점수를 계산합니다. + +**품질 점수 (0–100):** +- 트렌드 강도, 경쟁 기사 수, 키워드 밀도 반영 +- **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 2–4: 번호 매긴 핵심 포인트 +- 마지막 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.04–0.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/테크를 누구나 따라할 수 있게 | 주 2–3회 | -| **숨은 보물** | 모르면 손해인 무료 도구 발굴 | 주 2–3회 | -| **바이브 리포트** | 비개발자가 AI로 만든 실제 사례 | 주 1–2회 | -| **팩트체크** | 과대광고/거짓 주장 검증 (수동 승인 필수) | 주 1회 이하 | -| **한 컷** | AI/테크 이슈 만평 | 주 1회 | +| 코너 | 성격 | 글 길이 | 안전장치 | +|------|------|---------|---------| +| **쉬운세상** | 복잡한 이슈를 쉽게 해설 | 1,500–2,000자 | 자동 발행 | +| **숨은보물** | 유용하지만 덜 알려진 정보 | 1,500–2,000자 | 자동 발행 | +| **바이브리포트** | 트렌드·문화 분석 | 1,500–2,500자 | 자동 발행 | +| **팩트체크** | [사실]/[의견]/[추정] 명시 검증 | 2,000–2,500자 | **수동 승인 필수** | +| **한컷** | 시사 만평 + 짧은 코멘트 | 300–500자 | 자동 발행 | -### 안전장치 (자동 발행 차단 조건) - -아래 조건에 해당하면 자동 발행 대신 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 1–3 | 블로그 1개, 시스템 검증, AdSense 승인 | 0–5만원/월 | -| **2** | Month 3–5 | 블로그 2개, 쿠팡 수익 집중 | 5–20만원/월 | -| **3** | Month 5–8 | 3–4개 블로그, 어필리에이트 추가 | 10–50만원/월 | -| **4** | Month 8+ | 영문 블로그, 글로벌 확장 | 30–100만원+/월 | +이 프로젝트는 [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 본문 필수 구성요소:** +- `