428th-exchange-bot/bot/config.py
Artemii Peretiachenko 8f6d2c07d6 Initial commit: 428th exchange Telegram bot.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-20 18:19:53 +02:00

104 lines
3.1 KiB
Python

from __future__ import annotations
import os
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, Optional
from dotenv import load_dotenv
load_dotenv()
DEFAULT_CLIENT_COOLDOWN_SECONDS = 5.0
@dataclass(frozen=True)
class Config:
bot_token: str
manager_group_id: int
database_path: Path
# Optional per-language overrides for i18n keys (lang -> text).
welcome_text: Dict[str, str]
ack_text: Dict[str, str]
cooldown_text: Dict[str, str]
client_cooldown_seconds: float
def _optional_env(name: str) -> Optional[str]:
raw = os.getenv(name)
if raw is None:
return None
value = raw.strip()
return value or None
def _text_overrides_for(key: str) -> Dict[str, str]:
"""Load per-language text overrides.
Supported env vars (example for welcome):
WELCOME_TEXT_RU / WELCOME_TEXT_UK — language-specific
WELCOME_TEXT — legacy; applies only to default language (ru), so UK
keeps its catalog string and the services button stays consistent.
"""
from bot.i18n import DEFAULT_LANGUAGE, SUPPORTED_LANGUAGES
overrides: Dict[str, str] = {}
legacy = _optional_env(key)
if legacy is not None:
overrides[DEFAULT_LANGUAGE] = legacy
for lang in SUPPORTED_LANGUAGES:
specific = _optional_env(f"{key}_{lang.upper()}")
if specific is not None:
overrides[lang] = specific
return overrides
def load_config() -> Config:
token = os.getenv("BOT_TOKEN", "").strip()
if not token:
raise RuntimeError("BOT_TOKEN is not set")
group_raw = os.getenv("MANAGER_GROUP_ID", "").strip()
if not group_raw:
raise RuntimeError("MANAGER_GROUP_ID is not set")
try:
manager_group_id = int(group_raw)
except ValueError as exc:
raise RuntimeError("MANAGER_GROUP_ID must be an integer") from exc
db_path = Path(os.getenv("DATABASE_PATH", "data/bot.db")).expanduser()
cooldown_raw = os.getenv("CLIENT_COOLDOWN_SECONDS", str(DEFAULT_CLIENT_COOLDOWN_SECONDS))
try:
client_cooldown_seconds = float(cooldown_raw)
except ValueError as exc:
raise RuntimeError("CLIENT_COOLDOWN_SECONDS must be a number") from exc
if client_cooldown_seconds < 0:
raise RuntimeError("CLIENT_COOLDOWN_SECONDS must be >= 0")
return Config(
bot_token=token,
manager_group_id=manager_group_id,
database_path=db_path,
welcome_text=_text_overrides_for("WELCOME_TEXT"),
ack_text=_text_overrides_for("ACK_TEXT"),
cooldown_text=_text_overrides_for("COOLDOWN_TEXT"),
client_cooldown_seconds=client_cooldown_seconds,
)
def apply_text_overrides(config: Config) -> None:
"""Apply optional env text overrides into the i18n catalog (per language)."""
from bot.i18n import TEXTS
for lang, text in config.welcome_text.items():
if lang in TEXTS:
TEXTS[lang]["welcome"] = text
for lang, text in config.ack_text.items():
if lang in TEXTS:
TEXTS[lang]["ack"] = text
for lang, text in config.cooldown_text.items():
if lang in TEXTS:
TEXTS[lang]["cooldown"] = text