import os from dataclasses import dataclass from pathlib import Path from dotenv import load_dotenv BASE_DIR = Path(__file__).resolve().parent load_dotenv(BASE_DIR / ".env", override=True) def env_bool(name: str, default: bool = False) -> bool: value = os.getenv(name) if value is None: return default return value.strip().lower() in {"1", "true", "yes", "on"} @dataclass(frozen=True) class Config: app_name: str = os.getenv("APP_NAME", "API接口系统") host: str = os.getenv("APP_HOST", os.getenv("API_HOST", "0.0.0.0")) port: int = int(os.getenv("APP_PORT", os.getenv("API_PORT", "7788"))) debug: bool = env_bool("APP_DEBUG", env_bool("API_DEBUG", False)) secret_key: str = os.getenv("SECRET_KEY", "replace-this-secret-key") api_key: str = os.getenv("API_KEY", "change-me") session_cookie_secure: bool = env_bool("SESSION_COOKIE_SECURE", False) db_host: str = os.getenv("DB_HOST", "127.0.0.1") db_port: int = int(os.getenv("DB_PORT", "3306")) db_user: str = os.getenv("DB_USER", "api_reader") db_password: str = os.getenv("DB_PASSWORD", "") db_name: str = os.getenv("DB_NAME", "member_system") db_charset: str = os.getenv("DB_CHARSET", "utf8mb4") db_connect_timeout: int = int(os.getenv("DB_CONNECT_TIMEOUT", "5")) members_table: str = os.getenv("MEMBERS_TABLE", "members") withdraw_table: str = os.getenv("WITHDRAW_TABLE", "withdraw_records") withdraw_request_table: str = os.getenv( "WITHDRAW_REQUEST_TABLE", "withdraw_request_records" ) deposit_table: str = os.getenv("DEPOSIT_TABLE", "deposit_records") read_only_mode: bool = env_bool("READ_ONLY_MODE", True) auto_init_sim_tables: bool = env_bool("AUTO_INIT_SIM_TABLES", False) default_activity_id: str = os.getenv("DEFAULT_ACTIVITY_ID", "ad-x1234") deposit_search_hours: int = int(os.getenv("DEPOSIT_SEARCH_HOURS", "24")) max_orders: int = int(os.getenv("MAX_ORDERS", "50")) # Chatwoot 網站客服設定 chatwoot_enabled: bool = env_bool("CHATWOOT_ENABLED", True) chatwoot_base_url: str = os.getenv( "CHATWOOT_BASE_URL", "http://pai.pubuli.com", ).rstrip("/") chatwoot_website_token: str = os.getenv( "CHATWOOT_WEBSITE_TOKEN", "Vivum4g1WWxH1AmxoTivAcX5", ) # 必須使用 Chatwoot Website Inbox 的 Identity Validation Token。 # 此值只保留在後端,絕不可輸出到 HTML 或 JavaScript。 chatwoot_identity_secret: str = os.getenv( "CHATWOOT_IDENTITY_SECRET", "", ) chatwoot_debug: bool = env_bool("CHATWOOT_DEBUG", False) chatwoot_account_id: int = int(os.getenv("CHATWOOT_ACCOUNT_ID", "1")) chatwoot_inbox_id: int = int(os.getenv("CHATWOOT_INBOX_ID", "1")) chatwoot_api_email: str = os.getenv("CHATWOOT_API_EMAIL", "") chatwoot_api_password: str = os.getenv("CHATWOOT_API_PASSWORD", "") chatwoot_greeting: str = os.getenv( "CHATWOOT_GREETING", "您好,欢迎光临【49彩票集团】客服服务中心,请问有什么可以帮到您的呢?", ) chatwoot_greeting_image: str = os.getenv( "CHATWOOT_GREETING_IMAGE", "static/guest_promo.png", ) chatwoot_guest_base_url: str = os.getenv( "CHATWOOT_GUEST_BASE_URL", "", ).rstrip("/") chatwoot_guest_website_token: str = os.getenv( "CHATWOOT_GUEST_WEBSITE_TOKEN", "", ) chatwoot_guest_proxy_target: str = os.getenv( "CHATWOOT_GUEST_PROXY_TARGET", "http://127.0.0.1:3000", ).rstrip("/") chatwoot_guest_api_base: str = os.getenv( "CHATWOOT_GUEST_API_BASE", "", ).rstrip("/") chatwoot_guest_api_email: str = os.getenv("CHATWOOT_GUEST_API_EMAIL", "") chatwoot_guest_api_password: str = os.getenv("CHATWOOT_GUEST_API_PASSWORD", "") chatwoot_guest_inbox_id: int = int(os.getenv("CHATWOOT_GUEST_INBOX_ID", "1")) chatwoot_widget_jwt_secret: str = os.getenv("CHATWOOT_WIDGET_JWT_SECRET", "") chatwoot_agent_bot_id: int = int(os.getenv("CHATWOOT_AGENT_BOT_ID", "0") or "0") chatwoot_agent_bot_token: str = os.getenv("CHATWOOT_AGENT_BOT_TOKEN", "") # 本機 Chatwoot → PAI MaxKB 橋接 maxkb_bridge_enabled: bool = env_bool("MAXKB_BRIDGE_ENABLED", True) maxkb_base_url: str = os.getenv( "MAXKB_BASE_URL", "http://pai.pubuli.com:8080", ).rstrip("/") maxkb_access_token: str = os.getenv("MAXKB_ACCESS_TOKEN", "") maxkb_timeout_sec: float = float(os.getenv("MAXKB_TIMEOUT_SEC", "120")) CONFIG = Config()