Личный bridge: сообщения из MAX (российский мессенджер) → Telegram Forum Supergroup. Каждый MAX-чат = отдельный топик. Reply в топике = ответ в MAX. Один пользователь, self-hosted, никаких третьих лиц.
- MAX подключается и получает входящие сообщения
- Новые чаты → автоматически создаётся топик в Telegram
- DM-топики переименовываются из "Чат XXXXX" в реальное имя контакта
- Фото, видео, аудио и документы пересылаются в Telegram
- Системные MAX-события (
leave,add, contact/sticker, edited/removed) рендерятся как текст - Reply из Telegram → сообщение уходит в MAX
- В Telegram topic могут писать участники группы, а не только owner
- В MAX исходящее из Telegram приходит с префиксом автора:
[Имя Фамилия] - Reconnect работает без OOM и без SSL-шторма
- Дедупликация: при reconnect сообщения не дублируются
- Bridge работает в production на Hetzner Cloud
-
Telegram API без retry — если TG API временно недоступен, сообщение может потеряться без повторной попытки.
-
Нет алерта при длительной потере MAX — bridge молча reconnect-ится. Если MAX недоступен > 1 минуты, пользователь не знает.
-
/statusпока слишком простой — отвечает "✅ Bridge работает", но без uptime, количества чатов и последней активности. -
SSH-доступ завязан на домашний IP — если IP сменится, нужно обновить правило и в Hetzner Firewall, и в
UFW.
Регулярные операции (deploy / backup / recover / bootstrap / hardening) теперь идут через Ansible — cd infra/ansible && ansible-playbook deploy.yml. Ручные шаги ниже остаются как fallback и для диагностики.
ssh -i ~/.ssh/id_rsa deploy@<SERVER_IP>
cd /opt/maxtg-bridge
docker compose --env-file .env.host -f deploy/docker-compose.prod.yml ps
docker compose --env-file .env.host -f deploy/docker-compose.prod.yml logs --tail=100 --since=10m
python3 scripts/smoke_check.py --db data/bridge.db --minutes 15| Файл | Зачем |
|---|---|
src/adapters/max_adapter.py |
pymax userbot, reconnect, парсинг сообщений |
src/adapters/tg_adapter.py |
aiogram, топики, send/recv |
src/bridge/core.py |
вся логика роутинга |
src/db/repository.py |
SQLite: bindings, dedup, delivery log |
config.yaml |
чаты, режимы, параметры |
scripts/smoke_check.py |
быстрый smoke-report по SQLite |
deploy/docker-compose.prod.yml |
production-compose для Hetzner |
infra/ansible/ |
playbooks: deploy / backup / recover / bootstrap / hardening |
docs/runbooks/operations.md |
ежедневная эксплуатация |
docs/runbooks/hetzner-production.md |
secure-runbook по серверу |
data/bridge.db |
состояние (не в git) |
message.sender—int, не User-объектmessage.chat_id—int; положительный = DM, отрицательный = группа- Имя пользователя:
user.names[0].first_name(неuser.first_name) - Кеш:
client.get_cached_user(int(user_id))— синхронный, работает client.me— атрибут (не методget_me())client.chats— список групп (populated после sync)SocketMaxClient(reconnect=True)→ OOM-баг:chats/dialogsрастут без сбросаsend_fake_telemetry=True(default) → SSL TLSV1_ALERT_RECORD_OVERFLOW на каждом connect- Правильный запуск:
reconnect=False, send_fake_telemetry=False+ outerwhile Trueloop
— вызов сразу после connect нестабилен, убрали; теперь rename происходит при первом входящем сообщенииfix_fallback_titles()при старте— нет такого метода, естьclient.get_me()client.me— правильное имя параметра именноsend_messageс параметромreply_toreply_to(неreply_to_message_id); проблема была в том, что сокет ещё не был готов
Добавить retry/backoff для Telegram API (src/adapters/tg_adapter.py).
Это сейчас самый полезный следующий шаг для production-качества.