from __future__ import annotations import os from dataclasses import dataclass from dotenv import load_dotenv BASE_DIR = os.path.dirname(os.path.abspath(__file__)) ENV_PATH = os.path.join(BASE_DIR, ".env") # override=True is intentional: the .env next to this bot is the source of truth. load_dotenv(ENV_PATH, override=True) def _csv_ints(value: str) -> set[int]: result: set[int] = set() for part in (value or "").split(","): part = part.strip() if not part: continue try: result.add(int(part)) except ValueError: pass return result def _clean_token(value: str) -> str: """ Accepts the normal Discord bot token format while removing common copy/paste errors: - surrounding quotes - accidental 'Bot ' prefix - leading/trailing whitespace """ token = (value or "").strip() if len(token) >= 2 and token[0] == token[-1] and token[0] in {'"', "'"}: token = token[1:-1].strip() if token.lower().startswith("bot "): token = token[4:].strip() return token @dataclass(frozen=True) class Settings: token: str = _clean_token(os.getenv("DISCORD_TOKEN", "")) service_owner_ids: set[int] = frozenset(_csv_ints(os.getenv("SERVICE_OWNER_IDS", ""))) global_log_channel_id: int = int(os.getenv("GLOBAL_LOG_CHANNEL_ID", "0") or 0) data_dir: str = (os.getenv("DATA_DIR", r"C:\NovaShieldData").strip() or r"C:\NovaShieldData") settings = Settings()