import os from dataclasses import dataclass from pathlib import Path from typing import Optional @dataclass(frozen=True) class AppConfig: secret_key: str database_path: Path mysql_host: str mysql_port: int mysql_user: str mysql_password: str mysql_database: str gogs_base_url: str gogs_token: Optional[str] require_login_to_view_repo: bool enable_mock_pay: bool max_preview_bytes: int # 支付宝中间层 REST API 配置 pay_api_base_url: str pay_return_url: str pay_callback_url: str def load_config() -> AppConfig: project_root = Path(__file__).resolve().parent.parent data_dir = project_root / "data" data_dir.mkdir(parents=True, exist_ok=True) # 自动加载 .env 文件(仅当环境变量未设置时生效) env_file = project_root / ".env" if env_file.exists(): with open(env_file, encoding="utf-8") as f: for line in f: line = line.strip() if not line or line.startswith("#") or "=" not in line: continue key, _, val = line.partition("=") key = key.strip() val = val.strip() if key and key not in os.environ: os.environ[key] = val return AppConfig( secret_key=os.environ.get("SECRET_KEY", "dev-secret-key"), database_path=Path(os.environ.get("DATABASE_PATH", str(data_dir / "app.db"))), mysql_host=(os.environ.get("MYSQL_HOST") or "").strip(), mysql_port=int(os.environ.get("MYSQL_PORT", "3306")), mysql_user=(os.environ.get("MYSQL_USER") or "").strip(), mysql_password=(os.environ.get("MYSQL_PASSWORD") or "").strip(), mysql_database=(os.environ.get("MYSQL_DATABASE") or "sourceshare").strip(), gogs_base_url=os.environ.get("GOGS_BASE_URL", "http://localhost:6066").rstrip("/"), gogs_token=os.environ.get("GOGS_TOKEN"), require_login_to_view_repo=os.environ.get("REQUIRE_LOGIN_TO_VIEW_REPO", "1") not in {"0", "false", "False"}, enable_mock_pay=os.environ.get("ENABLE_MOCK_PAY", "1") in {"1", "true", "True"}, max_preview_bytes=int(os.environ.get("MAX_PREVIEW_BYTES", "200000")), pay_api_base_url=(os.environ.get("PAY_API_BASE_URL") or "https://aigc-api.aitoolcore.com").rstrip("/"), pay_return_url=(os.environ.get("PAY_RETURN_URL") or "").strip(), pay_callback_url=(os.environ.get("PAY_CALLBACK_URL") or "").strip(), )