baekjoon-bot

작성: AI / 수정: nkey

매일 백준(BOJ) 문제를 추천해주고, 디스코드 메시지(payload)로 쓸 수 있는 형태로 반환하는 FastAPI 서비스입니다.
/today에서 추천 문제 + 링크 + Discord embed payload를 생성하며, (선택) PostgreSQL에 문제집(workbook) 진행상황을 저장해 “문제집에서 아직 안 보낸 문제”를 고르는 모드도 제공합니다.
디스코드 메시지 자동화는 n8n을 활용하였습니다.

Quickstart

# clone
git clone https://nkeystudy.site/gitea/nkey/baekjoon-bot.git
cd baekjoon-bot

# venv
python -m venv .venv
source .venv/bin/activate

# deps
pip install -r requirements.txt

# env (필수: DATABASE_URL)
cat > .env <<'EOF'
DATABASE_URL=postgresql+asyncpg://USER:PASSWORD@HOST:5432/DBNAME
# (admin API 사용 시 필수)
ADMIN_PASSWORD=change-me
EOF

# run
uvicorn app:app --host 0.0.0.0 --port 8000

# verify
curl -s http://localhost:8000/ | cat
curl -s "http://localhost:8000/today" | cat

Alternative (optional) - Docker

docker build -f dockerfile -t baekjoon-bot:local .
docker run --rm -p 8000:8000 --env-file .env baekjoon-bot:local

# verify
curl -s http://localhost:8000/ | cat

Requirements

  • Runtime/Language: Python 3.12+ (Dockerfile 기준)
  • Dependencies: fastapi, uvicorn, sqlalchemy>=2.0, asyncpg, requests, httpx, python-dotenv 등 (requirements.txt)
  • Tools: (optional) Docker

Configuration

Environment Variables

Key Description Default Required
DATABASE_URL SQLAlchemy async DB URL (예: postgresql+asyncpg://...) -
ADMIN_PASSWORD Admin API 인증 비밀번호 (X-Admin-Password 헤더와 비교) "" (admin API)
SOURCE_MODE_DEFAULT /today 기본 소스 모드 search
WORKBOOK_ID_DEFAULT source_mode=workbook에서 workbook_id 미지정 시 기본값 -
DIFFICULTY_MODE_DEFAULT /today 기본 난이도 모드 easy
TAG_MODE_DEFAULT /today 기본 태그 모드 easy
LANG_DEFAULT /today 기본 언어 all
DIFFICULTY_EASY easy 난이도 범위 6..10
DIFFICULTY_HARD hard 난이도 범위 11..15
DIFFICULTY_ALL all 난이도 범위 1..30
TAGS_EASY easy 태그 프리셋(CSV) ""
TAGS_HARD hard 태그 프리셋(CSV) ""
TAGS_ALL all 태그 프리셋(CSV) ""
TAG_PICK 태그 선택 정책 (random/none/전체) random
TAG_PICK_EASY easy 태그 선택 정책 TAG_PICK
TAG_PICK_HARD hard 태그 선택 정책 TAG_PICK
TAG_PICK_ALL all 태그 선택 정책 TAG_PICK 또는 none
TAGS_JOIN 태그 결합 방식 or

Ports

Service Port Description
API 8000 FastAPI(Uvicorn)

Usage (minimal)

  • 오늘의 추천 문제(검색 모드, 기본값)
    • GET /today
  • 난이도/태그/언어 지정
    • GET /today?difficulty=6..10&tags=dp,graphs&lang=ko,en
  • 문제집(workbook) 모드로 추천
    • GET /today?source_mode=workbook&workbook_id=12345&workbook_pick=level_asc
  • Admin: 문제집 메타(제목/레벨/태그) 보강
    • POST /admin/workbooks/{workbook_id}/enrich + X-Admin-Password: ...

Docs

  • Operations: docs/OPERATIONS.md
  • Development: docs/DEVELOPMENT.md
  • API: docs/API.md

CI/CD

  • Workflow: .gitea/workflows/cicd.yml
  • Trigger: main 브랜치로 push 시 실행
  • Flow:
    1. (수동) checkout: Gitea 서브패스(/gitea)를 고려해 git init + git fetch로 소스 가져옴
    2. Docker Hub 로그인
    3. 이미지 빌드/푸시: ${DOCKERHUB_USERNAME}/baekjoon-bot:latest
    4. 서버 배포: 서버에 존재하는 compose 파일(/nkeysworld/compose.yml)로 pull/up -d 수행
    5. Discord Webhook으로 성공/실패 알림 전송

Required Secrets

Key Used for
NKEY_PAT workflow 내 수동 checkout 시 Gitea repo fetch 인증
DOCKERHUB_USERNAME Docker Hub 이미지 네임스페이스
DOCKERHUB_TOKEN Docker Hub 로그인 토큰
DISCORD_WEBHOOK CI/CD 결과 알림 전송

NOTE: workflow의 빌드 단계는 docker build -t ... .(기본 Dockerfile 사용) 형태입니다. 레포의 빌드 파일명은 dockerfile(소문자)이므로, CI 환경에서 기본 Dockerfile을 쓰려면 파일명/옵션 정합성을 확인하세요.

Description
매일 백준 문제를 디스코드로 전달해주는 봇입니다.
Readme 105 KiB
Languages
Python 100%