feat(bot): точка входа, конфиг, главное меню, доступ для ADMIN_IDS, healthcheck
- config: pydantic-settings по подсистемам, ADMIN_IDS через запятую - texts.yaml + валидация при старте (лишний/пропущенный ключ — ошибка сразу) - меню: reply-клавиатура разделов (Участники — только админам), инлайн «Назад»/«Отмена» с редактированием сообщения на месте, /start, /menu, /help - AccessMiddleware (outer) на сообщениях и кнопках: до #25 пускает только ADMIN_IDS, постороннему — одна фраза в сутки, устаревшие кнопки молча гасятся - heartbeat-файл + HEALTHCHECK в Dockerfile; JSON-логи - FSM пока в памяти (фабрика), хранилище в БД — в #5 - тесты на фейковой сессии aiogram через настоящий Dispatcher Refs #4 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
"""UI texts from `config/texts.yaml`, validated at startup so a missing key fails fast instead of mid-dialog."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class _Strict(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid", frozen=True)
|
||||
|
||||
|
||||
class MenuTexts(_Strict):
|
||||
commit: str
|
||||
status: str
|
||||
logs: str
|
||||
alerts: str
|
||||
members: str
|
||||
back: str
|
||||
cancel: str
|
||||
placeholder: str
|
||||
|
||||
|
||||
class StartTexts(_Strict):
|
||||
welcome: str
|
||||
no_access: str
|
||||
|
||||
|
||||
class HelpTexts(_Strict):
|
||||
text: str
|
||||
|
||||
|
||||
class SectionTexts(_Strict):
|
||||
commit: str
|
||||
status: str
|
||||
logs: str
|
||||
alerts: str
|
||||
members: str
|
||||
cancelled: str
|
||||
|
||||
|
||||
class Texts(_Strict):
|
||||
menu: MenuTexts
|
||||
start: StartTexts
|
||||
help: HelpTexts
|
||||
section: SectionTexts
|
||||
|
||||
|
||||
def load_texts(config_dir: Path) -> Texts:
|
||||
with (config_dir / "texts.yaml").open(encoding="utf-8") as f:
|
||||
return Texts.model_validate(yaml.safe_load(f))
|
||||
Reference in New Issue
Block a user