Перейти к содержанию

Telegram Bot Integration

Источник: backend/app/services/telegram_bot.py, telegram_handler.py, api/v1/endpoints/telegram_webhook.py

Общие сведения

Параметр Значение
Режим Webhook (не polling)
Endpoint POST /api/v1/telegram/webhook
Библиотека httpx (async HTTP client, не python-telegram-bot)
Base URL https://api.telegram.org/bot{TOKEN}/
Токен settings.TELEGRAM_BOT_TOKEN (env)
Формат сообщений Markdown (parse_mode=Markdown)

Webhook Setup

POST /api/v1/telegram/set-webhook?url={webhook_url}
  • Вызывает bot.setWebhook(url=webhook_url)
  • Должен быть HTTPS URL
  • Настраивается вручную через endpoint (нет auto-setup при старте)

Debug Endpoints

Endpoint Назначение
GET /telegram/debug/webhook Показать текущий webhook (getWebhookInfo)
GET /telegram/debug/subscription/{business_id} Проверить подписку бизнеса

Команды бота

/start - Главная точка входа

Обрабатывает deep links через параметр после /start:

Deep Link Pattern Действие Пример
provider_{business_id} Привязка провайдера (PROVIDER_BUSINESS subscription) /start provider_5
client_{phone} Привязка клиента по телефону (CLIENT_PHONE subscription) /start client_77001234567
subscribe_{booking_id} Подписка на статус брони (CLIENT_BOOKING subscription) /start subscribe_42
(без параметра) Приветственное сообщение /start

Логика deep link provider_: 1. Извлечь business_id из параметра 2. Проверить существование бизнеса в БД 3. Сохранить telegram_chat_id в Business.telegram_chat_id 4. Создать/обновить Subscription(context_type=PROVIDER_BUSINESS, context_ref=business_id) 5. Ответить: "Уведомления для {business.name} включены!"

Логика deep link client_: 1. Извлечь телефон из параметра 2. Создать Subscription(context_type=CLIENT_PHONE, context_ref=phone) 3. Ответить: "Вы подписаны на уведомления по номеру {phone}"

Логика deep link subscribe_: 1. Извлечь booking_id 2. Проверить существование брони 3. Создать Subscription(context_type=CLIENT_BOOKING, context_ref=booking_id) 4. Ответить информацию о записи

Другие команды

Команда Описание
/help Список доступных команд
/unsubscribe Деактивация всех подписок текущего chat_id
/status Показать активные подписки текущего chat_id

Callback Queries (Inline Keyboards)

Управление бронированиями (провайдер)

callback_data Действие Результат
confirm_{booking_id} Подтвердить запись status -> confirmed, уведомление клиенту
reject_{booking_id} Отклонить запись status -> rejected, уведомление клиенту
reschedule_{booking_id} Начать перенос Показать выбор даты (кнопки дат)

Перенос записи (провайдер)

callback_data Действие
rh_{booking_id}_{hours} Выбрать час для переноса
rm_{booking_id}_{date}_{hour}_{minutes} Выбрать минуты -> создать RescheduleProposal

Ответ на перенос (клиент)

callback_data Действие
ra_{proposal_id} Принять перенос (status -> ACCEPTED, обновить booking.start_at)
rd_{proposal_id} Отклонить перенос (status -> DECLINED)

Формат уведомлений

Новая заявка (провайдеру)

Новая заявка на запись!

Клиент: {first_name}
Телефон: {phone}
Услуга: {service.name}
Мастер: {master.name}
Дата: {DD.MM.YYYY}
Время: {HH:MM}
Цена: {price} KZT
Комментарий: {notes}

Подтвердите или отклоните запись:
[Подтвердить] [Отклонить]
[Перенести]

Подтверждение записи (клиенту)

Запись ПОДТВЕРЖДЕНА

{business.name}
Услуга: {service.name}
Мастер: {master.name}
Дата: {DD.MM.YYYY}
Время: {HH:MM}
Адрес: {address}

Ждем вас!

Отмена (клиенту)

Запись ОТМЕНЕНА

{business.name}
Услуга: {service.name}
Мастер: {master.name}
Дата: {DD.MM.YYYY}
Время: {HH:MM}

Свяжитесь с салоном для записи на другое время.

Предложение переноса (клиенту)

Предложение о переносе

Мастер предлагает перенести запись:
Было: {DD.MM HH:MM}
Предложено: {DD.MM} в {HH:MM}
Услуга: {service.name}

Вам подходит это время?
[Подтвердить] [Отклонить]

Сброс пароля (провайдеру)

Сброс пароля Cita

Ваш новый пароль: {password}
Бизнес: {business.name}

Рекомендуем сменить пароль после входа в систему.

TelegramBotService API

Метод Telegram API Параметры
send_message(chat_id, text, keyboard?) sendMessage chat_id, text, parse_mode=Markdown, reply_markup
edit_message(chat_id, message_id, text, keyboard?) editMessageText chat_id, message_id, text, parse_mode, reply_markup
answer_callback_query(callback_id, text?) answerCallbackQuery callback_query_id, text
send_photo(chat_id, photo_bytes, caption?) sendPhoto chat_id, photo (multipart), caption, parse_mode

Ограничения и особенности

Ограничение Описание
Rate Limits Telegram: 30 msg/sec globally, 1 msg/sec per chat. Не обрабатывается в коде
Markdown Используется Markdown v1 (не MarkdownV2). Спецсимволы не экранируются
Нет retry Ошибки HTTP логируются, но повторных попыток нет
Нет очереди Сообщения отправляются синхронно в рамках request. Нет фоновой очереди
Нет группировки Каждое уведомление - отдельное сообщение. Нет batch/digest
Webhook only Polling не поддерживается. Webhook URL должен быть настроен вручную
Нет верификации Webhook не проверяет X-Telegram-Bot-Api-Secret-Token
Inline keyboards Используются для confirm/reject/reschedule. Кнопки обновляются через edit_message