Логика разговора, а не кнопки конструктора
Конструктор, в котором вы собираете сценарий, поменяется. Названия узлов, форма редактора, тарифы — всё это живёт полгода-год. Не меняется другое: разговор имеет состояние, у непонимания есть дно, у передачи человеку есть условие, а у отправки наружу — разрешение, повод и лимит. Эта лекция про вторую часть.
Разбираем два предмета. Первый — состояние разговора: то, что живёт между сообщениями и чего не видно в схеме. Второй — правила отправки: проверки, которые сценарий обязан выполнить в ту секунду, когда собирается написать человеку сам. Примеры сквозные и рабочие: квалификация заявки, напоминание о записи, триаж обращений в поддержку, уведомление о доставке, сбор данных перед передачей менеджеру.
- Что считается успехом этого диалога? Не «человек ответил», а измеримый исход на конкретном шаге: заявка квалифицирована, запись подтверждена, обращение отнесено к типу.
- Кто пишет первым? Если человек нам — это диалог. Если мы человеку — это отправка наружу, и у неё другой набор проверок, вплоть до штрафа.
- Чем разговор заканчивается? Исходов ровно три: цель достигнута, человек передан оператору, бот честно сказал, что не умеет. Четвёртого — «переспросил в шестой раз» — быть не должно.
Транспорта: как запрос доехал, как устроены вебхуки и повторы на уровне протокола — отдельная лекция про API и вебхуки. Методики тестирования, обработки сбоев и оповещений — отдельные лекции. Устройства шага с языковой моделью — отдельная лекция. Разбора закона о рекламе как закона, маркировки и споров с антимонопольным органом — лекции про звонки и про рекламу; здесь норма появляется только как проверка внутри сценария. Маркетингового календаря, жизненного цикла клиента и доставляемости писем — территория CRM-маркетолога.
Девятнадцать тем, тест после каждой. Числа в лекции — из документации платформ, текстов норм и рецензируемых статей; там, где источник заинтересован или цифра не проверяется, это сказано прямо.
Состояние разговора живёт не в кнопке
Человек нажал «Записаться», выбрал услугу, отвлёкся. Через двадцать минут вернулся и нажал «Далее». Что знает сценарий в эту секунду? Ровно то, что вы догадались сохранить, и ровно там, где вы это положили. Сообщение на экране — не память: это отпечаток одного хода.
Кнопка несёт ярлык, а не память
У inline-кнопки Telegram есть поле callback_data, и документация описывает его дословно: «Data to be sent in a callback query to the bot when the button is pressed, 1-64 bytes». Для сравнения, текст самого сообщения — «1-4096 characters after entities parsing».
Шестьдесят четыре байта — это место под ключ, а не под состояние. Положить в кнопку «что мы уже выяснили» физически нельзя: туда влезает идентификатор записи и код действия, не более. Отсюда самая частая поломка сценариев: автор кладёт в кнопку выбранную услугу, на второй ветке кладёт дату, на третьей понимает, что имя и телефон уже не помещаются, — и сценарий «забывает» ответ, который человек дал две минуты назад.
Правильная раскладка простая: в кнопке — ключ, в хранилище сценария — всё остальное. Ключ говорит «вот эта запись, вот это действие», хранилище отвечает, что в записи уже собрано.
После нажатия callback-кнопки клиент показывает индикатор загрузки, пока бот не вызвал answerCallbackQuery. Документация настаивает: «It is, therefore, necessary to react by calling answerCallbackQuery even if no notification to the user is needed». Ветка, которая ничего не отвечает, потому что «ответ придёт позже», выглядит для человека как зависший интерфейс — и он жмёт кнопку ещё раз, и ещё.
Что обязано лежать в состоянии
- идентификатор разговора и человека;
- что уже спросили и что получили — по каждому полю отдельно, а не одной строкой;
- на каком шаге стоим сейчас;
- сколько раз подряд мы не поняли ответ (счётчик, без которого не работает лестница переспросов);
- отметка «человек просил оператора» — она переживает любую ветку;
- отметка «по этому поводу этому человеку уже писали».
Проверьте на своём сценарии квалификации заявки: если убрать из него последнее сообщение бота, сможет ли он продолжить с того же места? Если нет — состояние живёт в переписке, а переписка не хранилище.
answerCallbackQuery необходимо, «even if no notification to the user is needed». Без вызова индикатор крутится, человек считает бота зависшим и дублирует нажатия — а сценарий получает дубли событий на ровном месте.Дальше нужен аккаунт
Прогресс и монеты сохранятся.