Данные сообщений
Ответ из ask, история getMessages, сообщения subscribeDialog и событие messageReceived используют общие данные сообщения. Они подходят для результата рядом с формой и для собственного чата.
Текст и идентификаторы
dialogIdиeventIdопределяют диалог и сообщение.textсодержит текст, аformatуказываетplain_textилиmarkdown.attachmentsсодержит вложения,buttons— строки кнопок.
Пустой text не означает ошибку: ответ может содержать только файл. Обычный текст выводите через textContent, а Markdown — через обработчик с очисткой небезопасного HTML. Не вставляйте полученный текст напрямую в innerHTML.
Версии, отправитель и ошибки
| Поле | Как использовать |
|---|---|
kind | message — обычное сообщение, error — сохранённая публичная ошибка. |
error | При ошибке может содержать message для посетителя. Внутреннего стека исключения здесь нет. |
version | Версия сообщения: обновляет существующую запись с тем же eventId, включая изменения вложений и кнопок. |
timestamp | Время сообщения для отображения и сортировки. |
sender | visitor, assistant, operator или system. Событие messageReceived ограничено assistant и operator. |
senderId, senderName, senderAvatarUrl | Необязательные данные отправителя; URL аватара также может быть null. |
sendingStatus | Необязательный статус отправки. Не заменяет итоговый статус запроса ask; учитывайте отсутствие или незнакомое значение. |
deleted | Сообщение удалено: уберите его содержимое или покажите пометку об удалении. |
Объединяйте сообщения одного диалога по eventId с учётом version. Экспорт mergeWidgetMessages(previous, incoming) из @senlerio/widget делает это и сортирует результат по времени. Он сохраняет записи с deleted, поэтому их содержимое должен скрывать интерфейс. Не добавляйте ответ второй раз, если он пришёл и через ask, и через подписку. Пример объединения — в инструкции своего чата.
Вложения
Каждое вложение содержит id, type и status. Типом может быть photo, video, document, voice, audio или sticker.
status: "ready" означает готовность файла. Состояния deferred, pending, fetching и uploading относятся к подготовке; quota_pending — к ожиданию доступной квоты, failed — к ошибке. При ошибке может быть указан errorCode. Ссылка не обязана быть доступна сразу.
Дополнительные поля, если они известны:
url— файл;previewUrl— изображение для предпросмотра;name,mimeType,size— имя, MIME-тип и размер в байтах;width,height— размеры изображения или видео;durationSeconds— длительность аудио или видео в секундах.
Для отправки файла посетителя используйте отдельный метод uploadFile, а затем передайте результат в ask.
Кнопки
buttons — массив строк вида { buttons: [...] }. У кнопки есть text и action. Действие содержит переход open_url, ответ callback или зарегистрированное действие сайта custom_action.
Дополнительные поля описывают состояние и оформление:
instanceId— идентификатор экземпляра кнопки;repeatable— разрешены повторные нажатия;disabled— кнопка выключена;appearance—neutral,primary,positiveилиnegative;pollOption.multiple— вариант опроса с возможностью множественного выбора.
Получение данных кнопки не означает её нажатия или подтверждения действия пользователем. В обработчике нажатия в собственном интерфейсе передайте исходную кнопку в clickButton:
async function clickMessageButton(message, button) {
if (button.disabled) return;
await widget.clickButton({
dialogId: message.dialogId,
eventId: message.eventId,
button,
});
}
widget — готовый экземпляр SDK, message и button — полученные данные. Обрабатывайте ошибку Promise в интерфейсе. Сервер проверяет идентификатор callback-кнопки, права и повторяемость нажатия. Для опроса с несколькими ответами передайте pollSelectedInstanceIds с выбранными instanceId вместе с кнопкой подтверждения. Не вызывайте действие при отрисовке истории.
Для custom_action используйте зарегистрированные обработчики. Завершение clickButton подтверждает выполнение команды, но не ожидание последующего ответа агента: его покажет подписка. Для open_url предпочтительна обычная ссылка <a> с полученным адресом, чтобы сохранить управление с клавиатуры и поведение браузера. У кнопки приветствия до создания диалога отдельный способ отправки.