Открытые линии
Операторы и передача диалога
Рабочая справка по операторам открытых линий: как смотреть оператора сессии, присоединяться, перехватывать и передавать диалог через PHP и REST.
Таблицы можно использовать для чтения состояния диалога. Управляющие действия — взять,
присоединиться, перехватить или передать — лучше выполнять штатными методами открытых линий:
через \Bitrix\ImOpenLines\Operator в коробочном PHP или через REST.
Операторы
Оператор сессии хранится в данных открытой линии, а участники чата — в IM-связях.
Где смотреть оператора
В сессиях открытых линий обычно полезны поля OPERATOR_ID,
CHAT_ID, STATUS, CONFIG_ID и даты сессии.
Для чтения можно использовать SessionTable. Для действий с диалогом лучше
не менять эти поля напрямую, а использовать \Bitrix\ImOpenLines\Operator.
Получить диалоги оператора
<?php
use Bitrix\Main\Loader;
use Bitrix\ImOpenLines\Model\SessionTable;
Loader::includeModule('imopenlines');
/**
* Получает последние сессии оператора.
*/
function fetchOperatorOpenLineSessions(int $operator_id, int $limit): array
{
$sessions = [];
$session_result = SessionTable::getList([
'select' => [
'ID',
'CHAT_ID',
'USER_CODE',
'CONFIG_ID',
'STATUS',
'OPERATOR_ID',
'DATE_CREATE',
'CLOSE_DATE',
],
'filter' => [
'=OPERATOR_ID' => $operator_id,
],
'order' => [
'ID' => 'DESC',
],
'limit' => $limit,
]);
while ($session = $session_result->fetch()) {
$sessions[] = $session;
}
return $sessions;
}
$sessions = fetchOperatorOpenLineSessions($operator_id, 50);
print_r($sessions); Действия с диалогом
Для действий с диалогом нужен CHAT_ID открытой линии. В PHP с ним
создаётся объект \Bitrix\ImOpenLines\Operator.
PHP: объект Operator
В коробочном PHP можно работать через класс
\Bitrix\ImOpenLines\Operator. Обычно ему передают CHAT_ID
открытой линии.
<?php
use Bitrix\Main\Loader;
use Bitrix\ImOpenLines\Operator;
Loader::includeModule('im');
Loader::includeModule('imopenlines');
/**
* Создаёт объект оператора открытой линии.
*/
function createOpenLineOperator(int $chat_id): ?Operator
{
if ($chat_id <= 0) {
return null;
}
return new Operator($chat_id);
}
/**
* Возвращает текст ошибки оператора.
*/
function fetchOpenLineOperatorError(Operator $operator): string
{
$error = $operator->getError();
if ($error === null) {
return '';
}
if (method_exists($error, 'getMessage')) {
return (string) $error->getMessage();
}
return print_r($error, true);
}
$operator = createOpenLineOperator($chat_id);
if ($operator === null) {
echo 'Не указан CHAT_ID';
} Действия выполняются от пользователя текущего PHP-контекста. Если код запускается из агента, cron или служебного скрипта, отдельно проверь, какой пользователь считается текущим и есть ли у него права на диалог.
PHP: присоединиться и перехватить
Для присоединения и перехвата у Operator есть методы
joinSession() и interceptSession(). Они полезны, когда
нужно выполнить действие из коробочного PHP-кода без REST-запроса.
<?php
use Bitrix\Main\Loader;
use Bitrix\ImOpenLines\Operator;
Loader::includeModule('im');
Loader::includeModule('imopenlines');
/**
* Присоединяет текущего оператора к диалогу.
*/
function joinOpenLineDialog(int $chat_id): array
{
$operator = createOpenLineOperator($chat_id);
if ($operator === null) {
return [
'is_success' => false,
'error_messages' => ['Не указан CHAT_ID'],
];
}
$is_success = (bool) $operator->joinSession();
return [
'is_success' => $is_success,
'error_messages' => $is_success ? [] : [fetchOpenLineOperatorError($operator)],
];
}
/**
* Перехватывает диалог текущим оператором.
*/
function interceptOpenLineDialog(int $chat_id): array
{
$operator = createOpenLineOperator($chat_id);
if ($operator === null) {
return [
'is_success' => false,
'error_messages' => ['Не указан CHAT_ID'],
];
}
$is_success = (bool) $operator->interceptSession();
return [
'is_success' => $is_success,
'error_messages' => $is_success ? [] : [fetchOpenLineOperatorError($operator)],
];
}
$join_result = joinOpenLineDialog($chat_id);
$intercept_result = interceptOpenLineDialog($chat_id);
print_r($join_result);
print_r($intercept_result);
Если метод вернул false, смотри ошибку через getError().
Частые причины: неверный CHAT_ID, это не чат открытой линии, текущий
пользователь не определён или у него нет доступа.
PHP: передать оператору
Для передачи конкретному пользователю можно вызвать
$operator->transfer() и передать TRANSFER_ID с ID
сотрудника.
<?php
use Bitrix\Main\Loader;
use Bitrix\ImOpenLines\Operator;
Loader::includeModule('im');
Loader::includeModule('imopenlines');
/**
* Передаёт диалог конкретному оператору.
*/
function transferOpenLineDialogToUser(int $chat_id, int $target_user_id): array
{
if ($target_user_id <= 0) {
return [
'is_success' => false,
'error_messages' => ['Не указан пользователь для передачи'],
];
}
$operator = createOpenLineOperator($chat_id);
if ($operator === null) {
return [
'is_success' => false,
'error_messages' => ['Не указан CHAT_ID'],
];
}
$is_success = (bool) $operator->transfer([
'TRANSFER_ID' => $target_user_id,
]);
return [
'is_success' => $is_success,
'error_messages' => $is_success ? [] : [fetchOpenLineOperatorError($operator)],
];
}
$transfer_result = transferOpenLineDialogToUser($chat_id, $target_user_id);
print_r($transfer_result);
Этот вариант ближе всего к REST-параметру USER_ID, но в PHP удобнее
использовать универсальный TRANSFER_ID.
PHP: передать в очередь
Для передачи в очередь другой открытой линии в TRANSFER_ID передаётся
строка вида queue123, где 123 — ID линии/очереди.
<?php
use Bitrix\Main\Loader;
use Bitrix\ImOpenLines\Operator;
Loader::includeModule('im');
Loader::includeModule('imopenlines');
/**
* Формирует идентификатор очереди для передачи.
*/
function buildOpenLineQueueTransferId(int $queue_id): string
{
return 'queue' . $queue_id;
}
/**
* Передаёт диалог в очередь другой открытой линии.
*/
function transferOpenLineDialogToQueue(int $chat_id, int $queue_id): array
{
if ($queue_id <= 0) {
return [
'is_success' => false,
'error_messages' => ['Не указана очередь для передачи'],
];
}
$operator = createOpenLineOperator($chat_id);
if ($operator === null) {
return [
'is_success' => false,
'error_messages' => ['Не указан CHAT_ID'],
];
}
$is_success = (bool) $operator->transfer([
'TRANSFER_ID' => buildOpenLineQueueTransferId($queue_id),
]);
return [
'is_success' => $is_success,
'error_messages' => $is_success ? [] : [fetchOpenLineOperatorError($operator)],
];
}
$transfer_result = transferOpenLineDialogToQueue($chat_id, $queue_id);
print_r($transfer_result);
Не путай QUEUE_ID с ID пользователя в очереди. Для передачи в линию нужен
именно ID очереди/линии, а в TRANSFER_ID он передаётся с префиксом
queue.
PHP: пропустить, завершить, спам
У Operator есть и другие методы для операторских действий. Их проще
оборачивать в одинаковый формат результата.
<?php
use Bitrix\Main\Loader;
use Bitrix\ImOpenLines\Operator;
Loader::includeModule('im');
Loader::includeModule('imopenlines');
/**
* Пропускает диалог к следующему оператору очереди.
*/
function skipOpenLineDialog(int $chat_id): array
{
$operator = createOpenLineOperator($chat_id);
if ($operator === null) {
return [
'is_success' => false,
'error_messages' => ['Не указан CHAT_ID'],
];
}
$is_success = (bool) $operator->skip();
return [
'is_success' => $is_success,
'error_messages' => $is_success ? [] : [fetchOpenLineOperatorError($operator)],
];
}
/**
* Завершает диалог текущего оператора.
*/
function closeOpenLineDialog(int $chat_id): array
{
$operator = createOpenLineOperator($chat_id);
if ($operator === null) {
return [
'is_success' => false,
'error_messages' => ['Не указан CHAT_ID'],
];
}
$is_success = (bool) $operator->closeDialog();
return [
'is_success' => $is_success,
'error_messages' => $is_success ? [] : [fetchOpenLineOperatorError($operator)],
];
}
/**
* Помечает диалог как спам.
*/
function markOpenLineDialogAsSpam(int $chat_id): array
{
$operator = createOpenLineOperator($chat_id);
if ($operator === null) {
return [
'is_success' => false,
'error_messages' => ['Не указан CHAT_ID'],
];
}
$is_success = (bool) $operator->markSpam();
return [
'is_success' => $is_success,
'error_messages' => $is_success ? [] : [fetchOpenLineOperatorError($operator)],
];
}
$skip_result = skipOpenLineDialog($chat_id);
$close_result = closeOpenLineDialog($chat_id);
$spam_result = markOpenLineDialogAsSpam($chat_id);
print_r($skip_result);
print_r($close_result);
print_r($spam_result); Для автоматизации лучше сначала проверить действие на тестовой открытой линии: эти методы меняют реальное состояние диалога, оператора, очереди и уведомлений.
REST: присоединиться к диалогу
Присоединение добавляет оператора к диалогу. В REST для этого используется
imopenlines.session.join.
/**
* Пример параметров REST-запроса для присоединения к диалогу.
*/
function buildJoinDialogPayload(int $chat_id): array
{
return [
'CHAT_ID' => $chat_id,
];
}
$payload = buildJoinDialogPayload($chat_id);
print_r($payload); REST: перехватить диалог
Перехват переводит текущий диалог на оператора, который вызывает действие. В REST для
этого используется imopenlines.session.intercept.
/**
* Пример параметров REST-запроса для перехвата диалога.
*/
function buildInterceptDialogPayload(int $chat_id): array
{
return [
'CHAT_ID' => $chat_id,
];
}
$payload = buildInterceptDialogPayload($chat_id);
print_r($payload); REST: передать диалог
Передача отправляет диалог другому оператору или в очередь. В REST для этого
используется imopenlines.operator.transfer.
/**
* Готовит параметры передачи диалога оператору.
*/
function buildTransferToUserPayload(int $chat_id, int $user_id): array
{
return [
'CHAT_ID' => $chat_id,
'USER_ID' => $user_id,
];
}
/**
* Готовит параметры передачи диалога в очередь.
*/
function buildTransferToQueuePayload(int $chat_id, int $queue_id): array
{
return [
'CHAT_ID' => $chat_id,
'QUEUE_ID' => $queue_id,
];
}
/**
* Готовит параметры передачи через универсальный TRANSFER_ID.
*/
function buildTransferPayload(int $chat_id, string $transfer_id): array
{
return [
'CHAT_ID' => $chat_id,
'TRANSFER_ID' => $transfer_id,
];
}
$user_payload = buildTransferToUserPayload($chat_id, $user_id);
$queue_payload = buildTransferToQueuePayload($chat_id, $queue_id);
$transfer_payload = buildTransferPayload($chat_id, 'queue' . $queue_id);
print_r($user_payload);
print_r($queue_payload);
print_r($transfer_payload);
В новых REST-методах также встречается универсальный параметр
TRANSFER_ID: ID пользователя или строка вида queue123.
Разница действий
Названия похожи, но смысл действий разный.
Взять, присоединиться, перехватить, передать
| Действие | PHP | REST | Как понимать |
|---|---|---|---|
| Взять | Operator::answer() | imopenlines.operator.answer | Оператор берёт новый или ожидающий диалог в работу. |
| Присоединиться | Operator::joinSession() | imopenlines.session.join | Оператор добавляется к текущему диалогу. |
| Перехватить | Operator::interceptSession() | imopenlines.session.intercept | Диалог переходит к оператору, который выполняет перехват. |
| Передать | Operator::transfer() | imopenlines.operator.transfer | Диалог отправляется другому оператору или в очередь. |
| Пропустить | Operator::skip() | imopenlines.operator.skip | Диалог уходит следующему оператору по очереди. |
| Завершить | Operator::closeDialog() | imopenlines.operator.finish | Текущий оператор завершает свой диалог. |
| Спам | Operator::markSpam() | imopenlines.operator.spam | Диалог помечается как спам и закрывается. |
Перед автоматизацией этих действий лучше проверить права пользователя, состояние сессии и текущего оператора. Прямое изменение таблиц для передачи диалога использовать не нужно.
Источники
- Официальная документация: модуль imopenlines
- Методы класса Operator модуля imopenlines
- Operator::transfer
- REST: Open Channel Operators overview
- REST: imopenlines.session.join
- REST: imopenlines.session.intercept
- REST: imopenlines.operator.transfer
- REST: imopenlines.operator.skip
- REST: imopenlines.bot.session.transfer