Files
baekjoon-bot/docs/DEVELOPMENT.md

3.4 KiB

Development Guide

작성: AI / 수정: nkey

Project Layout

  • app.py : FastAPI 엔트리포인트, 라우팅(/, /today, /admin/...)
  • utils.py : 환경변수 헬퍼, solved.ac 검색 쿼리 생성, admin 인증, solved.ac 검색 호출
  • db.py : SQLAlchemy Async 엔진/세션 및 get_db() DI
  • workbook_picker.py : DB에서 “아직 보내지 않은 문제” 1개 선택 + send 기록
  • workbook_enricher.py : solved.ac problem/show로 workbook 문제 메타(제목/레벨/태그) 채우기
  • workbook_importer.py : BOJ 문제집 페이지에서 문제 ID 수집 + DB upsert (현재 app.py에서 라우팅은 주석 처리됨)
  • requirements.txt : 파이썬 의존성
  • dockerfile : 컨테이너 실행 정의(uvicorn, 8000)

Prerequisites

  • Python 3.12+ 권장 (Docker 이미지 기준: python:3.12-slim)
  • PostgreSQL (workbook 모드/관리 API 사용 시)
  • pip / venv

Local Setup

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

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

cat > .env <<'EOF'
DATABASE_URL=postgresql+asyncpg://USER:PASSWORD@HOST:5432/DBNAME
ADMIN_PASSWORD=change-me
EOF

# FastAPI runs
uvicorn app:app --reload --host 0.0.0.0 --port 8000

# sanity check
curl -s http://localhost:8000/ | cat

Common Commands

레포에 Makefile/스크립트/테스트 명령이 따로 정의되어 있지 않아, 일반적인 실행 명령만 기재합니다.

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

# install deps
pip install -r requirements.txt

Environment Variables (Dev)

  • 필수: DATABASE_URL
  • Admin API 개발/테스트 시: ADMIN_PASSWORD
  • /today의 기본값을 바꾸려면 아래 변수를 사용:
    • SOURCE_MODE_DEFAULT, WORKBOOK_ID_DEFAULT
    • DIFFICULTY_MODE_DEFAULT, TAG_MODE_DEFAULT, LANG_DEFAULT
    • DIFFICULTY_EASY|HARD|ALL, TAGS_EASY|HARD|ALL, TAG_PICK*, TAGS_JOIN

DB/Migrations (if applicable)

  • 코드에서 참조하는 테이블(DDL은 레포에 없음):
    • workbooks, workbook_problems, workbook_sends
-- 1) 문제집
CREATE TABLE IF NOT EXISTS workbooks (
  id            BIGINT PRIMARY KEY,             -- BOJ workbook id 그대로 사용
  title         TEXT,
  source        TEXT NOT NULL DEFAULT 'boj',     -- 'boj' 고정(필요하면 확장)
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- 2) 문제집-문제 목록
CREATE TABLE IF NOT EXISTS workbook_problems (
  workbook_id   BIGINT NOT NULL REFERENCES workbooks(id) ON DELETE CASCADE,
  problem_id    INTEGER NOT NULL,
  title_ko      TEXT,
  title_en      TEXT,
  level         INTEGER,                         -- solved.ac level(0~30)
  tags          TEXT[] DEFAULT NULL,              -- optional
  added_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
  PRIMARY KEY (workbook_id, problem_id)
);

CREATE INDEX IF NOT EXISTS idx_workbook_problems_workbook
  ON workbook_problems(workbook_id);

-- 3) 발송/사용 기록(문제집 단위 중복 방지 핵심)
CREATE TABLE IF NOT EXISTS workbook_sends (
  workbook_id   BIGINT NOT NULL REFERENCES workbooks(id) ON DELETE CASCADE,
  problem_id    INTEGER NOT NULL,
  sent_at       TIMESTAMPTZ NOT NULL DEFAULT now(),
  PRIMARY KEY (workbook_id, problem_id)
);

CREATE INDEX IF NOT EXISTS idx_workbook_sends_workbook
  ON workbook_sends(workbook_id);