2026-05-07 16:31:56 +08:00

58 lines
2.0 KiB
Python

from __future__ import annotations
import os
from dataclasses import dataclass
from pathlib import Path
@dataclass(frozen=True)
class Config:
root_dir: Path
port: int
base_url: str
database_path: Path
employee_seed_path: Path
workday_calendar_path: Path
feishu_webhook_url: str
feishu_webhook_secret: str
feishu_app_id: str
feishu_app_secret: str
session_secret: str
def _read_dotenv(path: Path) -> dict[str, str]:
if not path.exists():
return {}
values: dict[str, str] = {}
for raw_line in path.read_text(encoding="utf-8").splitlines():
line = raw_line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
values[key.strip()] = value.strip().strip('"').strip("'")
return values
def read_config(env: dict[str, str] | None = None) -> Config:
root_dir = Path(__file__).resolve().parent.parent
dotenv_values = _read_dotenv(root_dir / ".env")
values = {**dotenv_values, **dict(env if env is not None else os.environ)}
port = int(values.get("PORT", "8787"))
if port <= 0:
raise ValueError("PORT must be a positive integer")
return Config(
root_dir=root_dir,
port=port,
base_url=values.get("BASE_URL", f"http://localhost:{port}"),
database_path=(root_dir / values.get("DATABASE_PATH", "data/daily-report.sqlite")).resolve(),
employee_seed_path=(root_dir / values.get("EMPLOYEE_SEED_PATH", "data/employees.json")).resolve(),
workday_calendar_path=(root_dir / values.get("WORKDAY_CALENDAR_PATH", "data/workday-calendar.json")).resolve(),
feishu_webhook_url=values.get("FEISHU_WEBHOOK_URL", ""),
feishu_webhook_secret=values.get("FEISHU_WEBHOOK_SECRET", ""),
feishu_app_id=values.get("FEISHU_APP_ID", ""),
feishu_app_secret=values.get("FEISHU_APP_SECRET", ""),
session_secret=values.get("SESSION_SECRET") or values.get("FEISHU_APP_SECRET") or "dev-session-secret",
)