Telegram Bot Integration
1. Summary
Goal: Telegram Bot служит центральной точкой интеграции с Telegram для goLoot платформы. Обеспечивает регистрацию пользователей, отправку push-уведомлений, публикацию интерактивных квизов и tracking конверсий через session activation flow.
User Value:
- Получение push-уведомлений о событиях платформы
- Участие в квизах прямо в Telegram discussion group и заработок Scrap
- Seamless onboarding через
/startкоманду - Отслеживание конверсий из маркетинговых кампаний (UTM/Referral)
2. Business Logic
Types / Variants
- Push Notifications
- Quiz Publication
- Session Activation
Individual Push — отправка одному пользователю через PushSendingService
Mass Broadcast — массовая рассылка через BroadcastService:
- Батчи по 25 пользователей
- 1 секунда между батчами (соблюдение Telegram 30 msg/sec)
- Retry с exponential backoff (3 попытки)
Scheduled Push — отложенная отправка через PushSchedulerService:
- Cron каждую минуту проверяет PENDING pushes
- Восстановление зависших SENDING > 10 мин
Click Tracking — отслеживание кликов через PushRedirect:
- Короткие ссылки с уникальным кодом
- Подсчёт clicksCount
Auto-publish — автоматическая публикация квиза после поста в канале
Fisher-Yates Shuffle — перемешивание вариантов ответов:
- Порядок сохраняется в
PublishedQuiz.shuffledOrder - При ответе восстанавливается оригинальный индекс
Real-time Statistics — обновление статистики в сообщении:
- "X ответов • Y% правильных"
- Обновляется после каждого ответа
Expiration — автоудаление:
- Production: 24 часа
- Test mode: 30 секунд
Три типа сессий:
| Тип | Паттерн startParam | Бонус |
|---|---|---|
| REFERRAL | ref_{code} | Via ReferralRewardService |
| CONTENT | content_{id} | — |
| UTM | Любой другой код | 200 Scrap |
Two-phase Flow:
/create-session— до валидации Telegram/activate-session— после валидации подписки
Защита от self-referral — referrer.telegramId !== body.telegramId
Core Mechanics
1. /start Command Handler
User sends /start
↓
Create or update User in DB
↓
Save chatId for push notifications
↓
Set botStatus = ACTIVE (or REACTIVATED if was BLOCKED)
↓
Record UserBotInteraction
↓
Send welcome message with WebApp button
2. Push Notification Flow
Admin creates push (PENDING)
↓
PushSchedulerService picks up (scheduledFor <= NOW)
↓
BroadcastService splits into batches (25 users)
↓
PushSendingService sends to each user
↓
Analytics recorded (SENT/FAILED)
↓
Bot-blocked detection → update user status
3. Quiz Answer Flow
User clicks answer button
↓
RateLimiterService checks limits (50/sec global, 10/min user)
↓
Check duplicate answer
↓
Restore shuffled order from PublishedQuiz.shuffledOrder
↓
Validate answer correctness
↓
Award Scrap + Update stats
↓
Update message with real-time statistics
↓
Process passive income for referrer
↓
Update achievement/quest progress
4. Session Activation Flow
Frontend: /create-session (startParam, telegramId)
↓
Parse session type (ref_*, content_*, UTM code)
↓
Create InviteSession (PENDING state)
... Frontend validates subscription via TG Mini App ...
Frontend: /activate-session (initData with HMAC signature)
↓
Validate Telegram signature (HMAC-SHA256)
↓
Check auth_date < 24h
↓
Activate sessions
↓
Award bonuses (UTM: 200 scrap, Referral: via ReferralRewardService)
↓
Update botStatus to ACTIVE
Protection
| Action | Rate Limit | Auth | Validation |
|---|---|---|---|
| check-bot | botCheck (30/min) | none | CheckBotRegistrationSchema |
| webhook | botCheck (30/min) | none | TelegramWebhookSchema |
| create-session | botCheck (30/min) | none | CreateSessionSchema |
| activate-session | botCheck (30/min) | Telegram HMAC | ActivateSessionSchema |
| quiz answer | RateLimiter (50/sec + 10/min) | none | — |
| broadcast | mutations (5/min) | admin | BroadcastSchema |
См. Security Matrix для полного обзора защит.
Telegram Data Validation
HMAC-SHA256 проверка:
secretKey = HMAC-SHA256("WebAppData", BOT_TOKEN)
hash = HMAC-SHA256(secretKey, dataCheckString)
dataCheckString = отсортированные параметры через \n
auth_date должен быть < 24 часов
Реализация: bot.routes.ts:554-592
Retry Configuration (PushSchedulerService)
| Попытка | Задержка |
|---|---|
| 1 | 5 мин |
| 2 | 15 мин |
| 3 | 45 мин |
| Max | 60 мин |
Формула: delay × 3^retryCount (capped at 60 min)
Edge Cases
Что видит пользователь (UI):
| Ситуация | UI поведение |
|---|---|
| Bot blocked | Push не доставляется, botStatus → BLOCKED |
| Quiz expired (24h) | Кнопки неактивны, сообщение удалено |
| NEW_USER 14+ days | Аккаунт физически удалён (cleanup job) |
| Invalid TG signature | 400 Bad Request, "Invalid hash signature" |
| Photo upload fails | Fallback на текстовое сообщение |
| Код | HTTP | Описание |
|---|---|---|
INVALID_HASH_SIGNATURE | 400 | Невалидная подпись Telegram |
AUTH_DATE_EXPIRED | 400 | auth_date старше 24 часов |
SELF_REFERRAL | 400 | Попытка использовать свой реферальный код |
SESSION_NOT_FOUND | 404 | Сессия не найдена |
RATE_LIMIT_EXCEEDED | 429 | Превышен лимит запросов |
3. ADR (Architectural Decisions)
Factory Pattern для инициализации бота
Проблема: Grammy Bot требует async инициализации (bot.init()) до того, как handlers смогут получить доступ к bot.botInfo. Стандартный конструктор не может быть async.
Решение: Статический factory метод TelegramBotService.create() гарантирует полную инициализацию бота до создания сервиса.
Альтернативы (отклонены):
- Lazy initialization — усложняет код, потенциальные race conditions
- Init в конструкторе с Promise — anti-pattern, нельзя await
Последствия: Сервис всегда имеет полностью инициализированный бот, чистый код.
Composition over Inheritance для сервисов
Проблема: TelegramBotService превращался в "God Object" с 800+ строками, обрабатывающими push, quiz, rate limiting, broadcast.
Решение: Выделение в фокусные сервисы (RateLimiterService, TelegramQuizService, PushSendingService, BroadcastService), композиция через dependency injection.
Последствия:
- Single Responsibility Principle
- Простое тестирование (mock отдельных сервисов)
- Переиспользуемые сервисы
TelegramBotService — это Orchestrator, не монолит. Вся бизнес-логика живёт в composed сервисах.
Fisher-Yates Shuffle с сохранением порядка
Проблема: Кнопки ответов квиза должны быть перемешаны случайно, но валидация ответа должна знать, какой оригинальный вариант был выбран.
Решение:
- Перемешать варианты используя Fisher-Yates
- Сохранить
shuffledOrderмассив в PublishedQuiz - При ответе маппить shuffledIndex обратно в originalIndex
Последствия: Честная рандомизация + корректная валидация ответов.
Hybrid Debounce+Throttle для статистики квизов
Проблема: При высокой активности (100+ ответов в минуту) каждый ответ триггерит editMessage → риск достичь Telegram rate limit (30 msg/sec) и создать ненужную нагрузку на API.
Решение: In-memory MessageUpdateManager с hybrid подходом:
- Debounce 1s — группировка burst-ов (rapid sequential updates)
- Throttle 2s — минимальный интервал между API вызовами (защита от rate limits)
- Force update после 10 pending — защита от infinite debounce при постоянном потоке
- Fresh data fetching — запрос актуальной статистики в момент выполнения, а не в момент планирования
Альтернативы (отклонены):
- Redis + Bull Queue — over-engineering для нашей нагрузки, добавляет зависимость
- Pure debounce — риск infinite delay при постоянном потоке ответов
- Pure throttle — не группирует rapid updates, больше API вызовов чем нужно
- WebSockets — не поддерживается Telegram Bot API
Последствия:
- 80-90% reduction API calls (100 ответов → 5-10 обновлений)
- Real-time ощущение для пользователей (задержка 1-2 секунды)
- Нет риска rate limit даже при viral quiz
Каждые 5 минут логируется эффективность: totalScheduled, totalPerformed, debounceMerged, savings.
4. Architecture
Services Overview
Key Components
| Компонент | Путь | Описание |
|---|---|---|
| TelegramBotService | backend/src/domains/telegram/bot.service.ts | Orchestrator, композиция сервисов, webhook/polling |
| TelegramQuizService | backend/src/domains/telegram/services/telegram-quiz.service.ts | Публикация квизов, обработка ответов, real-time stats |
| PushSendingService | backend/src/domains/telegram/services/push-sending.service.ts | Отправка push, bot-blocked detection |
| BroadcastService | backend/src/domains/telegram/services/broadcast.service.ts | Массовая рассылка, batch processing, retry |
| PushSchedulerService | backend/src/domains/telegram/services/push-scheduler.service.ts | Cron-scheduling, stuck push recovery |
| RateLimiterService | backend/src/domains/telegram/services/rate-limiter.service.ts | Global/user rate limiting, auto-cleanup |
| TelegramSubscriptionService | backend/src/domains/telegram/services/telegram-subscription.service.ts | Проверка подписки на канал |
| Bot Routes | backend/src/domains/telegram/bot.routes.ts | API endpoints, session flow, TG validation |
| Start Handler | backend/src/domains/telegram/handlers/start.handler.ts | /start command, user creation, chatId capture |
5. Database Schema
Models
| Модель | Описание | Ключевые поля |
|---|---|---|
| PushNotification | Конфигурация push + статистика | title, message, status, scheduledFor, sentCount |
| PushAnalytics | Tracking доставки/открытий | pushId, userId, action, messageId, errorCode |
| PushRedirect | Click tracking с короткими ссылками | shortCode, originalUrl, clicksCount |
| PushBatch | Записи batch processing | pushId, batchNumber, successCount, failureCount |
| UserBotInteraction | Логирование действий бота | userId, action, metadata |
| PublishedQuiz | Опубликованные квизы | quizId, messageId, shuffledOrder, expiresAt |
| InviteSession | UTM/Referral tracking сессии | type, telegramId, state, metadata |
Relationships
Enums
| Enum | Values | Usage |
|---|---|---|
| BotRegistrationState | NEW_USER, ACTIVE, BLOCKED, REACTIVATED | User.botStatus |
| PushStatus | PENDING, SENDING, SENT, FAILED, CANCELLED | PushNotification.status |
| PushAction | SENT, DELIVERED, OPENED, CLICKED | PushAnalytics.action |
| InviteType | UTM, REFERRAL | InviteSession.type |
| InviteSessionState | PENDING, ACTIVATED, EXPIRED | InviteSession.state |
6. API Endpoints
- User API
- Admin: Push
- Admin: Broadcast
- Admin: Scheduler
| Метод | Эндпоинт | Описание | Docs |
|---|---|---|---|
| POST | /api/tg/check-bot-registration | Проверка статуса бота | -> |
| POST | /api/tg/webhook | Telegram webhook receiver | -> |
| POST | /api/tg/create-session | Создание UTM/referral сессии | -> |
| POST | /api/tg/activate-session | Активация сессии после TG валидации | -> |
| Метод | Эндпоинт | Описание | Docs |
|---|---|---|---|
| GET | /admin/push | Список push-уведомлений | -> |
| POST | /admin/push | Создание push | -> |
| PUT | /admin/push/:id | Редактирование push | -> |
| DELETE | /admin/push/:id | Удаление push | -> |
| POST | /admin/push/:id/send | Отправить сейчас | -> |
| GET | /admin/push/stats | Статистика push | -> |
Admin Notifications (Topic Routing)
AdminNotificationService отправляет уведомления в разные топики Telegram-группы:
| Топик | События | Описание |
|---|---|---|
SEASONS | SEASON_STARTED, SEASON_ENDED, SEASON_REWARDS_NEEDED, SEASON_ENDING_SOON | Жизненный цикл сезонов |
RAFFLES | RAFFLE_PRIZE_POOL_EMPTY | Проблемы с розыгрышами |
BUDGET | POOL_UPDATE, PERIOD_TRANSITION | Экономика и пул удачи |
SECURITY | BUDGET_EXHAUSTED, SUSPICIOUS_CRAFTS | Безопасность и фрод |
BAN_APPEAL | BAN_APPEAL_SUBMITTED | Апелляции банов |
Каждое событие содержит inline keyboard со ссылками на админ-панель.
Компонент: admin-notification.service.ts
7. Related
- Quizzes — CRUD контента квизов, статистика
- Referrals — Обработка реферальных бонусов, passive income
- UTM Tracking — Управление UTM кампаниями
- Onboarding — Проверка подписок, регистрация
- Profile — Управление User.botStatus
- Seasons — Уведомления о сезонах