[bot][A] Telegram-адаптер (aiogram 3) поверх движка #11

Closed
opened 2026-10-03 14:38:54 +03:00 by Eleboba · 0 comments
Owner

Описание

Реальный канал для демо на синтетике. Тонкий слой: апдейт → get_engine().handle() → рендер Reply (inline-кнопки); deep-link /start <код>; реализует Outbox для пушей шедулера. Подключается через app/channels/telegram.py: start()/stop() (уже вызываются из main). Без TG_BOT_TOKEN — no-op. В логах нет текста.

Зона и владение файлами

Lane A (бот, Егор) — владеет: app/dialog/**, app/channels/**, app/llm/**, config/texts/**, tests/test_dialog_*.py, tests/test_telegram*.py.

Замороженные контракты (менять только отдельным мелким PR с пингом всех): app/core/types.py, app/dialog/contracts.py, app/api/schemas.py, app/integrations/base.py, app/services/contracts.py, app/main.py, app/config.py, config/modules.yaml, config/rules.yaml, config/scales/*, pyproject.toml/uv.lock, docker-compose.yml, Makefile.


Лог выполнения

2026-10-03

  • Что сделано: app/channels/telegram.py — TelegramChannel (логика без типов aiogram) + build_router() (aiogram 3) + start()/stop(). /start <код> → integrations.identity.verify(code) → привязка tg_chat_id в identity-БД (ChatDirectory, кэш chat↔token; повторная привязка чата к другому пациенту освобождает старую) → Event(type="start", params={"code"}). Текст/кнопки привязанного чата → Event(text|button); непривязанный чат получает «откройте ссылку/QR от врача». Ответы: Button → inline-клавиатура (callback_data > 64 байт отбрасывается), длинный текст режется по строкам до 4096, parse_mode=None — кризисный скрипт уходит дословно. После нажатия кнопки клавиатура снимается (нельзя ответить дважды), перед ответом движка — «печатает…». TelegramOutbox доставляет пуши шедулера в привязанный чат, иначе — в прежний outbox (веб-консоль). Служебные тексты — config/texts/telegram.yaml.
  • Результат: 16 тестов tests/test_telegram.py (включая прогон реальных апдейтов через aiogram Dispatcher с фейковой HTTP-сессией). make lint test — 528 passed.
  • Заметки/решения: канал — граница регистрации, поэтому ему можно в identity-БД (guardrail #5). В логах только тип события и префикс токена, без chat id и текста. До #14 RejectIdentity отклоняет любой код — для живой проверки нужен esia_mock. Уведомления врачу в Telegram (DOCTOR_NOTIFY_CHAT_ID) — это Notifier зоны B (#14), здесь не делал. Ошибка движка → нейтральное «попробуйте позже».
## Описание Реальный канал для демо на синтетике. Тонкий слой: апдейт → `get_engine().handle()` → рендер `Reply` (inline-кнопки); deep-link `/start <код>`; реализует `Outbox` для пушей шедулера. Подключается через `app/channels/telegram.py: start()/stop()` (уже вызываются из main). Без `TG_BOT_TOKEN` — no-op. В логах нет текста. ## Зона и владение файлами **Lane A (бот, Егор)** — владеет: `app/dialog/**`, `app/channels/**`, `app/llm/**`, `config/texts/**`, `tests/test_dialog_*.py`, `tests/test_telegram*.py`. **Замороженные контракты** (менять только отдельным мелким PR с пингом всех): `app/core/types.py`, `app/dialog/contracts.py`, `app/api/schemas.py`, `app/integrations/base.py`, `app/services/contracts.py`, `app/main.py`, `app/config.py`, `config/modules.yaml`, `config/rules.yaml`, `config/scales/*`, `pyproject.toml`/`uv.lock`, `docker-compose.yml`, `Makefile`. --- ## Лог выполнения ### 2026-10-03 - **Что сделано:** `app/channels/telegram.py` — `TelegramChannel` (логика без типов aiogram) + `build_router()` (aiogram 3) + `start()/stop()`. `/start <код>` → `integrations.identity.verify(code)` → привязка `tg_chat_id` в identity-БД (`ChatDirectory`, кэш chat↔token; повторная привязка чата к другому пациенту освобождает старую) → `Event(type="start", params={"code"})`. Текст/кнопки привязанного чата → `Event(text|button)`; непривязанный чат получает «откройте ссылку/QR от врача». Ответы: `Button` → inline-клавиатура (callback_data > 64 байт отбрасывается), длинный текст режется по строкам до 4096, `parse_mode=None` — кризисный скрипт уходит дословно. После нажатия кнопки клавиатура снимается (нельзя ответить дважды), перед ответом движка — «печатает…». `TelegramOutbox` доставляет пуши шедулера в привязанный чат, иначе — в прежний outbox (веб-консоль). Служебные тексты — `config/texts/telegram.yaml`. - **Результат:** 16 тестов `tests/test_telegram.py` (включая прогон реальных апдейтов через aiogram Dispatcher с фейковой HTTP-сессией). `make lint test` — 528 passed. - **Заметки/решения:** канал — граница регистрации, поэтому ему можно в identity-БД (guardrail #5). В логах только тип события и префикс токена, без chat id и текста. До #14 `RejectIdentity` отклоняет любой код — для живой проверки нужен esia_mock. Уведомления врачу в Telegram (`DOCTOR_NOTIFY_CHAT_ID`) — это `Notifier` зоны B (#14), здесь не делал. Ошибка движка → нейтральное «попробуйте позже».
Eleboba added this to the Этап 1 · Ветераны СВО milestone 2026-10-03 14:38:54 +03:00
Eleboba added the P1size/0.5botfeature labels 2026-10-03 14:38:54 +03:00
Eleboba self-assigned this 2026-10-03 14:38:54 +03:00
Eleboba changed title from [bot] Telegram-адаптер (aiogram 3) поверх движка to [bot][A] Telegram-адаптер (aiogram 3) поверх движка 2026-10-03 15:16:29 +03:00
Eleboba added the lane/Astage/veterans labels 2026-10-03 15:16:29 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: MedITron/PTSRaiAgent#11