"""全局配置:球队信息、品牌色、数据库连接。 存储采用 DATABASE_URL 开关: - 默认本地 SQLite(零配置,数据存 data/team.db) - 部署时设置环境变量 DATABASE_URL 指向云端 Postgres,代码无需改动 """ from __future__ import annotations import logging import os from pathlib import Path from typing import Optional logger = logging.getLogger(__name__) # 目录 BASE_DIR: Path = Path(__file__).resolve().parent.parent DATA_DIR: Path = BASE_DIR / "data" WWW_DIR: Path = BASE_DIR / "www" DATA_DIR.mkdir(exist_ok=True) # 数据库:本地 SQLite 兜底,环境变量可切换到 Postgres 等 _raw_db_url: str = os.environ.get( "DATABASE_URL", f"sqlite:///{(DATA_DIR / 'team.db').as_posix()}" ) # 兼容 Neon / Supabase 等直接给出的连接串:统一改用 psycopg(v3) 驱动, # 这样用户把云平台复制的 postgres:// 或 postgresql:// 串直接粘进来即可,无需手改。 if _raw_db_url.startswith("postgres://"): _raw_db_url = "postgresql+psycopg://" + _raw_db_url[len("postgres://"):] elif _raw_db_url.startswith("postgresql://"): _raw_db_url = "postgresql+psycopg://" + _raw_db_url[len("postgresql://"):] DATABASE_URL: str = _raw_db_url # 球队品牌 TEAM_NAME: str = "肆带贰" TEAM_NAME_EN: str = "SHENZHEN SI DAI ER FC" TEAM_CITY: str = "深圳" EST_YEAR: int = 2024 CREST_URL: str = "/static/crest.jpg" # 由 static_assets 挂载 # 初始密码:正式部署请通过环境变量 SDE_DEFAULT_PASSWORD 提供。 # 未设置时退回内置兜底(仅供本地开发/演示),并打 WARNING 提醒。 # 字面量只在这一处出现,避免散落硬编码。 _DEFAULT_PASSWORD_FALLBACK = "sde2024" DEFAULT_PASSWORD: str = os.environ.get("SDE_DEFAULT_PASSWORD") or _DEFAULT_PASSWORD_FALLBACK if DEFAULT_PASSWORD == _DEFAULT_PASSWORD_FALLBACK: logger.warning( "正在使用内置默认初始密码,请勿用于生产;" "正式部署请设置环境变量 SDE_DEFAULT_PASSWORD,并提醒队员首次登录后修改密码。" ) # ---------------------------------------------------------------- 钻石球星卡(专属外观) # 允许名单:名单内的账号在「我的数据」页会把自己的球星卡显示为专属「钻石」皮肤。 # 说明:这是纯外观开关,只影响 my_fifa_card 这一处(且只有本人登录才看得到自己)。 # OVR 评分、六维、档位阈值、主页卡墙、各类榜单、导出图片一律不受影响—— # 钻石卡上的数字仍是系统真实计算的 OVR,只是换了一层皮肤。 # 匹配规则:用 username(登录名)或 display_name(显示名)任一命中即可,大小写不敏感。 # 环境变量 SDE_DIAMOND_USERS(逗号分隔)可在部署时追加,无需改代码。 DIAMOND_IDENTIFIERS: frozenset[str] = frozenset( {"hwl"} | { s.strip().lower() for s in os.environ.get("SDE_DIAMOND_USERS", "").split(",") if s.strip() } ) def is_diamond_user(user: Optional[dict]) -> bool: """该登录用户是否启用钻石皮肤(纯外观判断,不触及任何数据/评分)。""" if not user: return False keys = { str(user.get("username", "")).strip().lower(), str(user.get("display_name", "")).strip().lower(), } return bool(keys & DIAMOND_IDENTIFIERS)