58 lines
2.0 KiB
Python
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",
|
|
)
|