uawdijnntqw1x1x1
IP : 18.191.120.131
Hostname : axolotl
Kernel : Linux axolotl 4.9.0-13-amd64 #1 SMP Debian 4.9.228-1 (2020-07-05) x86_64
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,
OS : Linux
PATH:
/
var
/
www
/
axolotl
/
data
/
www
/
kirov.axolotls.ru
/
bitrix
/
modules
/
imopenlines
/
lib
/
session.php
/
/
<?php namespace Bitrix\ImOpenLines; use \Bitrix\Main, \Bitrix\Main\Loader, \Bitrix\Main\Application, \Bitrix\Main\Type\DateTime, \Bitrix\Main\Localization\Loc, \Bitrix\Main\DB\SqlExpression; use \Bitrix\ImOpenLines\Log\Library, \Bitrix\Imopenlines\Im\Messages, \Bitrix\ImOpenLines\Log\EventLog, \Bitrix\ImOpenLines\Session\Agent, \Bitrix\ImOpenLines\Model\SessionTable, \Bitrix\ImOpenLines\Model\SessionCheckTable, \Bitrix\Imopenlines\Model\SessionIndexTable; Loc::loadMessages(__FILE__); class Session { private $config = []; private $session = []; private $user = []; private $connectorId = ''; /* @var \Bitrix\ImOpenLines\Chat */ public $chat = null; private $action = 'none'; public $joinUserId = 0; public $joinUserList = []; private $isCreated = false; const RULE_TEXT = 'text'; const RULE_FORM = 'form'; const RULE_NONE = 'none'; const ACTION_NO_ANSWER = 'no_answer'; const ACTION_CLOSED = 'closed'; const ACTION_NONE = 'none'; const MODE_INPUT = 'input'; const MODE_OUTPUT = 'output'; const CACHE_QUEUE = 'queue'; const CACHE_CLOSE = 'close'; const CACHE_MAIL = 'mail'; const CACHE_INIT = 'init'; const CACHE_NO_ANSWER = 'no_answer'; /** New dialog opens. */ const STATUS_NEW = 0; /** The operator sent the dialog to the queue. */ const STATUS_SKIP = 5; /** The operator took the dialogue to work. */ const STATUS_ANSWER = 10; /** The client is waiting for the operator's response. */ const STATUS_CLIENT = 20; /** The client is waiting for the operator's answer (new question after answer). */ const STATUS_CLIENT_AFTER_OPERATOR = 25; /** The operator responded to the client. */ const STATUS_OPERATOR = 40; /** The dialogue in the mode of closing (pending the vote or after auto-answer). */ const STATUS_WAIT_CLIENT = 50; /** The conversation has ended. */ const STATUS_CLOSE = 60; /** Spam / forced termination. */ const STATUS_SPAM = 65; /** Duplicate session. The session is considered closed. */ const STATUS_DUPLICATE = 69; /** Closed without sending special messages and notifications. */ const STATUS_SILENTLY_CLOSE = 75; const ORM_SAVE = 'save'; const ORM_GET = 'get'; const VOTE_LIKE = 5; const VOTE_DISLIKE = 1; /** * Session constructor. * @param array $config * @throws Main\LoaderException */ public function __construct($config = []) { $this->config = $config; Loader::includeModule('im'); } /** * Initialization of the session by the given data. * * @param array $session Array describing the session. * @param array $config An array describing the setting of an open line. * @param array $chat An array describing the chat. */ public function loadByArray($session, $config, $chat) { $this->session = $session; $this->config = $config; $this->chat = $chat; $this->connectorId = $session['SOURCE']; Debug::addSession($this, __METHOD__); } /** * Session load method. * * @param array $params * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function load(array $params) { $result = false; $parsedUserCode = Session\Common::parseUserCode($params['USER_CODE']); $parsedUserCodeFail = $parsedUserCode; if (empty($params['CONFIG_ID'])) { $params['CONFIG_ID'] = $parsedUserCode['CONFIG_ID']; } $params['USER_ID'] = $parsedUserCode['CONNECTOR_USER_ID']; $params['SOURCE'] = $parsedUserCode['CONNECTOR_ID']; $params['CHAT_ID'] = $parsedUserCode['EXTERNAL_CHAT_ID']; if(Connector::isEnableGroupByChat($parsedUserCode['CONNECTOR_ID'])) { $parsedUserCode['CONNECTOR_USER_ID'] = 0; if(!empty($params['USER_ID'])) { $params['USER_CODE_FAIL'] = $params['USER_CODE']; } $params['USER_CODE'] = Session\Common::combineUserCode($parsedUserCode); } else { //Handles the situation where the group chat feature or not has been changed. $parsedUserCodeFail['CONNECTOR_USER_ID'] = 0; $params['USER_CODE_FAIL'] = Session\Common::combineUserCode($parsedUserCodeFail); } $resultStart = $this->start($params); if($resultStart->isSuccess() && $resultStart->getResult() == true) { $result = true; } return $result; } /** * @param $params * @return Result * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function start($params) { Debug::addSession($this, 'begin ' . __METHOD__, $params); $result = new Result(); $result->setResult(false); //params $this->connectorId = $params['SOURCE']; $fields['PARENT_ID'] = intval($params['PARENT_ID']); $fields['USER_CODE'] = $params['USER_CODE']; $fields['USER_CODE_FAIL'] = $params['USER_CODE_FAIL']; $fields['CONFIG_ID'] = intval($params['CONFIG_ID']); $fields['USER_ID'] = intval($params['USER_ID']); $fields['OPERATOR_ID'] = intval($params['OPERATOR_ID']); $params['CRM_TRACE_DATA'] = (string)$params['CRM_TRACE_DATA']; $fields['SOURCE'] = $params['SOURCE']; $fields['MODE'] = $params['MODE'] == self::MODE_OUTPUT? self::MODE_OUTPUT: self::MODE_INPUT; $params['DEFERRED_JOIN'] = $params['DEFERRED_JOIN'] == 'Y'? 'Y': 'N'; $params['SKIP_CREATE'] = $params['SKIP_CREATE'] == 'Y'? 'Y': 'N'; $params['REOPEN'] = $params['REOPEN'] == 'Y'? 'Y': 'N'; $configManager = new Config(); //Check open line configuration load if (empty($this->config) && !empty($fields['CONFIG_ID'])) { $this->config = $configManager->get($fields['CONFIG_ID']); } if (empty($this->config)) { $result->addError(new Error(Loc::getMessage('IMOL_SESSION_ERROR_NO_IMOL_CONFIGURATION'), 'NO IMOL CONFIGURATION', __METHOD__, $params)); } if($result->isSuccess()) { if($this->prepareUserChat($params) !== true || empty($this->chat)) { $result->addError(new Error(Loc::getMessage('IMOL_SESSION_ERROR_NO_CHAT'), 'NO CHAT', __METHOD__, $params)); } } //END params if($result->isSuccess()) { //Load session $resultReading = $this->readingSession($fields, $params); if($resultReading->isSuccess()) { if($resultReading->getResult() == true) { $result->setResult(true); } //If you do create a session else if ($params['SKIP_CREATE'] != 'Y') { //Creating a new session $resultCreate = $this->createSession($fields, $params); if($resultCreate->isSuccess()) { $result->setResult(true); } else { $result->addErrors($resultCreate->getErrors()); } //END Creating a new session } } else { $result->addErrors($resultReading->getErrors()); } } Debug::addSession($this, 'end ' . __METHOD__, ['SUCCESS' => $result->isSuccess(), 'ERRORS' => $result->getErrorMessages()]); return $result; } /** * @param $fields * @param $params * @return Result * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ protected function createSession($fields, $params) { Debug::addSession($this, 'begin ' . __METHOD__, ['fields' => $fields, '$params' => $params]); $result = new Result(); /* CRM BLOCK */ $crmManager = new Crm($this); if($crmManager->isLoaded()) { $crmFieldsManager = $crmManager->getFields(); $crmFieldsManager->setDataFromUser($fields['USER_ID']); if($this->config['CRM_CREATE'] != Config::CRM_CREATE_LEAD) { $crmManager->setSkipCreate(); } if(Connector::isNeedCRMTracker($fields['SOURCE'])) { $crmManager->setSkipCreate(); $crmManager->setIgnoreSearchPerson(); } $fields['CRM_TRACE_DATA'] = Crm\Tracker::getTraceData($params['CRM_TRACE_DATA']); } /* END CRM BLOCK */ if ($fields['MODE'] === self::MODE_OUTPUT) { $previousSessionBlock = ReplyBlock::getBlockFromPreviousSession($fields); } $fields['CHAT_ID'] = $this->chat->getData('ID'); if ($this->chat->isNowCreated()) { $fields['START_ID'] = 0; $fields['IS_FIRST'] = 'Y'; } else { $fields['START_ID'] = $this->chat->getData('LAST_MESSAGE_ID')+1; $fields['IS_FIRST'] = 'N'; $this->chat->join($fields['USER_ID']); } if ($fields['MODE'] == self::MODE_OUTPUT) { $fields['STATUS'] = self::STATUS_ANSWER; } $resultAdd = Model\SessionTable::add($fields); if ($resultAdd->isSuccess()) { $this->isCreated = true; $fields['SESSION_ID'] = $resultAdd->getId(); $resultAddSessionCheck = Model\SessionCheckTable::add([ 'SESSION_ID' => $fields['SESSION_ID'], 'DATE_CLOSE' => (new DateTime())->add('180 SECONDS'), 'DATE_QUEUE' => (new DateTime())->add('180 SECONDS'), ]); if($resultAddSessionCheck->isSuccess()) { $this->session = $fields; $this->session['ID'] = $this->session['SESSION_ID'] = $fields['SESSION_ID']; $dateNoAnswer = null; $queueManager = Queue::initialization($this); $resultQueue = $queueManager->createSession($fields['OPERATOR_ID'], $crmManager, Connector::isEnableGroupByChat($fields['SOURCE'])); $this->session['JOIN_BOT'] = $resultQueue['JOIN_BOT']; $this->session['OPERATOR_ID'] = $fields['OPERATOR_ID'] = $params['OPERATOR_ID'] = $resultQueue['OPERATOR_ID']; $fields['DATE_OPERATOR'] = $resultQueue['DATE_OPERATOR']; $fields['QUEUE_HISTORY'] = $this->session['QUEUE_HISTORY'] = $resultQueue['QUEUE_HISTORY']; $dateNoAnswer = $resultQueue['DATE_NO_ANSWER']; $undistributed = $resultQueue['UNDISTRIBUTED'] == true? 'Y' : 'N'; $dateQueue = $resultQueue['DATE_QUEUE']; $this->joinUserList = $resultQueue['OPERATOR_LIST']; $fields['OPERATOR_FROM_CRM'] = $resultQueue['OPERATOR_CRM'] == true? 'Y' : 'N'; //Send message if ($fields['PARENT_ID'] > 0) { $messageId = Messages\Session::sendMessageStartSessionByMessage($fields['CHAT_ID'], $fields['SESSION_ID'], $fields['PARENT_ID']); } else { $messageId = Messages\Session::sendMessageStartSession($fields['CHAT_ID'], $fields['SESSION_ID']); } //END Send message if ($this->chat->isNowCreated()) { if(intval($messageId) < 0) { $messageId = 0; } $fields['START_ID'] = $messageId; } $this->chat->updateFieldData([Chat::FIELD_SESSION => [ 'ID' => $fields['SESSION_ID'], 'DATE_CREATE' => new DateTime() ]]); if ($fields['MODE'] == self::MODE_INPUT) { /* CLOSED LINE */ if ($this->config['ACTIVE'] == 'N') { $this->action = self::ACTION_CLOSED; $fields['WORKTIME'] = 'N'; $fields['WAIT_ACTION'] = 'Y'; } else if(!(new AutomaticAction\WorkTime($this))->isWorkTimeLine()) { $fields['WORKTIME'] = 'N'; if ($this->session['JOIN_BOT']) { $this->resetActionAll(); } else { $fields['WAIT_ACTION'] = 'Y'; } } } elseif ($fields['MODE'] == self::MODE_OUTPUT) { if ($this->config['ACTIVE'] == 'N') { $this->action = self::ACTION_CLOSED; $fields['WORKTIME'] = 'N'; $fields['WAIT_ACTION'] = 'Y'; } if ($fields['OPERATOR_ID']) { if ($this->chat->getData('AUTHOR_ID') == 0) { $this->chat->answer($fields['OPERATOR_ID'], true); $this->chat->join($fields['OPERATOR_ID']); } } $fields['WAIT_ANSWER'] = 'N'; } $sessionId = $fields['SESSION_ID']; unset($fields['SESSION_ID']); Model\SessionTable::update($sessionId, $fields); $fields['SESSION_ID'] = $sessionId; if ( $fields['MODE'] == self::MODE_INPUT && !empty($this->joinUserList) && $params['DEFERRED_JOIN'] == 'N' ) { $this->chat->sendJoinMessage($this->joinUserList, $fields['OPERATOR_FROM_CRM']); $this->chat->join($this->joinUserList); $this->joinUserList = []; } $dateClose = new DateTime(); if ($fields['MODE'] == self::MODE_INPUT) { $dateClose->add('1 MONTH'); } else { $dateClose->add($this->config['AUTO_CLOSE_TIME'] . ' SECONDS'); } Model\SessionCheckTable::update($fields['SESSION_ID'], [ 'DATE_CLOSE' => $dateClose, 'DATE_QUEUE' => $dateQueue, 'DATE_NO_ANSWER' => $dateNoAnswer, 'UNDISTRIBUTED' => $undistributed, ]); $sessionManager = Model\SessionTable::getByIdPerformance($fields['SESSION_ID']); $this->session = $sessionManager->fetch(); $this->session['SESSION_ID'] = $this->session['ID']; $this->session['CHECK_DATE_CLOSE'] = $dateClose; $this->session['CHECK_DATE_QUEUE'] = $dateQueue; if (!empty($previousSessionBlock['BLOCK_DATE']) && !empty($previousSessionBlock['BLOCK_REASON'])) { ReplyBlock::add($fields['SESSION_ID'], $this->chat, $previousSessionBlock); } elseif (Loader::includeModule('imconnector')) { $limit = \Bitrix\ImConnector\Connector::getReplyLimit($fields['SOURCE']); if ($limit) { $limit['BLOCK_DATE'] = (new DateTime())->add($limit['BLOCK_DATE'].' SECONDS'); ReplyBlock::add($fields['SESSION_ID'], $this->chat, $limit); Messages\Session::sendMessageTimeLimit($fields['CHAT_ID'], $limit['BLOCK_REASON']); } } /* BLOCK STATISTIC*/ ConfigStatistic::getInstance($fields['CONFIG_ID'])->addInWork()->addSession(); /* END BLOCK STATISTIC*/ /* CRM BLOCK */ if ($fields['MODE'] == self::MODE_INPUT) { if (!Connector::isEnableGroupByChat($fields['SOURCE']) && $this->config['CRM'] == 'Y' && $crmManager->isLoaded()) { $crmFieldsManager->setTitle($this->chat->getData('TITLE')); $crmManager->setDefaultFlags(); $crmManager->registrationChanges(); $crmManager->sendCrmImMessages(); } else { $crmManager->setDefaultFlags(); } } elseif ($fields['MODE'] == self::MODE_OUTPUT) { if($this->config['CRM'] == 'Y' && $crmManager->isLoaded()) { $crmFieldsManager->setTitle($this->chat->getData('TITLE')); $crmManager->registrationChanges(); $crmManager->sendCrmImMessages(); } } /* END CRM BLOCK */ /* Event */ $eventData['SESSION'] = $this->session; $eventData['RUNTIME_SESSION'] = $this; $eventData['CONFIG'] = $this->config; $event = new \Bitrix\Main\Event("imopenlines", "OnSessionStart", $eventData); $event->send(); /* END Event */ if (Connector::isLiveChat($this->session['SOURCE'])) { $parsedUserCode = Session\Common::parseUserCode($this->session['USER_CODE']); \Bitrix\Pull\Event::add($this->session['USER_ID'], [ 'module_id' => 'imopenlines', 'command' => 'sessionStart', 'params' => [ 'chatId' => (int)$parsedUserCode['EXTERNAL_CHAT_ID'], 'sessionId' => (int)$this->session['ID'], ] ]); } } else { $result->addErrors($resultAddSessionCheck->getErrors()); } } else { $result->addErrors($resultAdd->getErrors()); } Debug::addSession($this, 'end ' . __METHOD__, ['SUCCESS' => $result->isSuccess(), 'ERRORS' => $result->getErrorMessages()]); return $result; } /** * @param array $params * @return Result * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function getLast(array $params): Result { $result = new Result(); if (empty($params['USER_CODE'])) { $result->addError(new Error(Loc::getMessage('IMOL_SESSION_ERROR_NO_USER_CODE'), 'NO IMOL CONFIGURATION', __METHOD__)); } $select = Model\SessionTable::getSelectFieldsPerformance(); $orm = Model\SessionTable::getList([ 'select' => $select, 'filter' => [ '=USER_CODE' => $params['USER_CODE'], ], 'order' => ['ID' => 'DESC'], 'limit' => 1 ]); $loadSession = $orm->fetch(); if (!empty($loadSession)) { $loadSession['SESSION_ID'] = $loadSession['ID']; $this->session = $loadSession; $this->chat = new Chat($this->session['CHAT_ID']); $configManager = new Config(); $this->config = $configManager->get($loadSession['CONFIG_ID']); } else { $result->addError(new Error(Loc::getMessage('IMOL_SESSION_ERROR_NO_LAST_SESSION'), 'NO LAST SESSION', __METHOD__)); } return $result; } /** * @param $fields * @param $params * @return Result * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ protected function readingSession($fields, $params) { Debug::addSession($this, 'begin ' . __METHOD__, ['fields' => $fields, '$params' => $params]); $result = new Result(); $result->setResult(false); $configManager = new Config(); $loadSession = false; $select = Model\SessionTable::getSelectFieldsPerformance(); $select['CHECK_DATE_CLOSE'] = 'CHECK.DATE_CLOSE'; $select['CHECK_DATE_QUEUE'] = 'CHECK.DATE_QUEUE'; $userCode = $fields['USER_CODE']; if(!empty($fields['USER_CODE_FAIL'])) { $userCode = [$fields['USER_CODE'], $fields['USER_CODE_FAIL']]; } $orm = Model\SessionTable::getList([ 'select' => $select, 'filter' => [ '=USER_CODE' => $userCode, '=CLOSED' => 'N' ], 'order' => ['ID' => 'DESC'] ]); while($row = $orm->fetch()) { if ( $row['USER_CODE'] == $fields['USER_CODE'] && empty($loadSession) ) { $loadSession = $row; } //Closes non-closed sessions else { try { self::closeDuplicate( [ 'ID' => $row['ID'], 'CHAT_ID' => $row['CHAT_ID'], 'OPERATOR_ID' => $row['OPERATOR_ID'], ], [ 'CHAT_ID' => $loadSession['CHAT_ID'], 'OPERATOR_ID' => $loadSession['OPERATOR_ID'], ] ); } catch (\Exception $e) { } } } //There is no open session, but the session voting if ( empty($loadSession) && ( $params['VOTE_SESSION'] == 'Y' || $params['REOPEN'] == 'Y' ) ) { $select = Model\SessionTable::getSelectFieldsPerformance(); $select['CHECK_DATE_CLOSE'] = 'CHECK.DATE_CLOSE'; $select['CHECK_DATE_QUEUE'] = 'CHECK.DATE_QUEUE'; $orm = Model\SessionTable::getList([ 'select' => $select, 'filter' => [ '=USER_CODE' => $fields['USER_CODE'], '=CLOSED' => 'Y', ], 'order' => ['ID' => 'DESC'] ]); $loadSession = $orm->fetch(); if (empty($loadSession) || $loadSession['WAIT_VOTE'] != 'Y') { $loadSession = false; } } if ($loadSession) { $loadSession['SESSION_ID'] = $loadSession['ID']; $this->session = $loadSession; if($params['VOTE_SESSION'] == 'Y') { $this->session['VOTE_SESSION'] = true; } if ($fields['CONFIG_ID'] != $this->session['CONFIG_ID']) { $this->config = $configManager->get($this->session['CONFIG_ID']); if (!empty($this->config)) { $fields['CONFIG_ID'] = $this->session['CONFIG_ID']; } else { $result->addError(new Error(Loc::getMessage('IMOL_SESSION_ERROR_NO_IMOL_CONFIGURATION'), 'NO IMOL CONFIGURATION', __METHOD__, $params)); } } if($result->isSuccess()) { $this->chat = new Chat($this->session['CHAT_ID']); //If the session is closed and voting if ($params['VOTE_SESSION'] == 'Y' && $loadSession['CLOSED'] == 'Y') { Messages\Session::sendMessageReopenSession($this->session['CHAT_ID'], $this->session['SESSION_ID']); //statistics ConfigStatistic::getInstance($this->session['CONFIG_ID'])->deleteClosed()->addInWork(); //statistics END $dateClose = new DateTime(); $fullCloseTime = $this->config['FULL_CLOSE_TIME']; if(!empty($fullCloseTime)) { $dateClose->add($fullCloseTime . ' MINUTES'); } $this->session['END_ID'] = 0; $this->session['CLOSED'] = 'N'; $this->session['WAIT_ANSWER'] = 'N'; $this->session['WAIT_ACTION'] = 'Y'; $this->session['PAUSE'] = 'N'; Model\SessionTable::update($loadSession['ID'], [ 'END_ID' => 0, 'CLOSED' => 'N', 'WAIT_ANSWER' => 'N', 'WAIT_ACTION' => 'Y', 'PAUSE' => 'N', //'STATUS' => self::STATUS_WAIT_CLIENT ]); Model\SessionCheckTable::add([ 'SESSION_ID' => $this->session['SESSION_ID'], 'DATE_CLOSE' => $dateClose ]); $this->chat->sendJoinMessage($this->joinUserList); $this->chat->join($this->session['OPERATOR_ID'], true, true); $this->chat->update(['AUTHOR_ID' => $this->session['OPERATOR_ID']]); $this->chat->updateFieldData([ Chat::FIELD_SESSION => [ 'ID' => $this->session['SESSION_ID'], 'PAUSE' => 'N', 'WAIT_ANSWER' => 'N', 'DATE_CREATE' => $this->session['DATE_CREATE']->getTimestamp() ], ]); } else if (!$this->chat->isNowCreated()) { $this->chat->join($fields['USER_ID']); } $result->setResult(true); } } Debug::addSession($this, 'end ' . __METHOD__, ['SUCCESS' => $result->isSuccess(), 'ERRORS' => $result->getErrorMessages()]); return $result; } /** * @param $params * @param int $count * @return bool * @throws Main\ArgumentException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ private function prepareUserChat($params, $count = 0) { $result = false; $resultUserRelation = \Bitrix\Imopenlines\Model\UserRelationTable::getByPrimary($params['USER_CODE'])->fetch(); if ($resultUserRelation) { if ($resultUserRelation['CHAT_ID']) { $this->chat = new Chat($resultUserRelation['CHAT_ID'], $params); if ($this->chat->isDataLoaded()) { $this->user = $resultUserRelation; $result = true; } } else if ($count <= 20) { usleep(500); $result = $this->prepareUserChat($params, ++$count); } } else if ($params['SKIP_CREATE'] != 'Y') { $params['USER_ID'] = intval($params['USER_ID']); \Bitrix\Imopenlines\Model\UserRelationTable::add([ 'USER_CODE' => $params['USER_CODE'], 'USER_ID' => $params['USER_ID'] ]); $this->chat = new Chat(); $this->chat->load([ 'USER_CODE' => $params['USER_CODE'], 'USER_ID' => $params['USER_ID'], 'LINE_NAME' => $this->config['LINE_NAME'], 'CONNECTOR' => $params['CONNECTOR'], ]); if ($this->chat->isDataLoaded()) { \Bitrix\Imopenlines\Model\UserRelationTable::update($params['USER_CODE'], ['CHAT_ID' => $this->chat->getData('ID')]); $resultUserRelation = [ 'USER_CODE' => $params['USER_CODE'], 'USER_ID' => $params['USER_ID'], 'CHAT_ID' => $this->chat->getData('ID'), 'AGREES' => 'N', ]; $this->user = $resultUserRelation; $result = true; } else { \Bitrix\Imopenlines\Model\UserRelationTable::delete($params['USER_CODE']); } } return $result; } /** * @param bool $active * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function pause($active = true) { $update = [ 'PAUSE' => $active? 'Y': 'N', ]; if ($active == 'Y') { $update['WAIT_ACTION'] = 'N'; } $this->update($update); Debug::addSession($this, __METHOD__); $this->addEventToLog(Library::EVENT_SESSION_PAUSE); return true; } /** * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function markSpam() { $this->update([ 'SPAM' => 'Y', 'WAIT_ANSWER' => 'N', 'DATE_MODIFY' => new DateTime(), ]); Debug::addSession($this, __METHOD__); $this->addEventToLog(Library::EVENT_SESSION_SPAM); return true; } /** * End of dialog. * * @param bool $auto * @param bool $force * @param bool $hideChat * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function finish($auto = false, $force = false, $hideChat = true) { $result = false; Debug::addSession($this, __METHOD__, ['auto' => $auto, 'force' => $force, 'hideChat' => $hideChat]); if (!empty($this->session)) { KpiManager::setSessionLastKpiMessageAnswered($this->session['ID']); $update = []; if ($force) { $this->session['CLOSED'] = 'Y'; $update['FORCE_CLOSE'] = 'Y'; } $currentDate = new DateTime(); if ($this->session['CHAT_ID']) { $chatData = \Bitrix\Im\Model\ChatTable::getById($this->session['CHAT_ID'])->fetch(); $lastMessageId = $chatData['LAST_MESSAGE_ID']; } else { $lastMessageId = 0; } if ($auto && $lastMessageId > 0) { $messageData = \Bitrix\Im\Model\MessageTable::getById($lastMessageId)->fetch(); if ($messageData) { $currentDate = clone $messageData['DATE_CREATE']; } } $userViewChat = \CIMContactList::InRecent($this->session['OPERATOR_ID'], IM_MESSAGE_OPEN_LINE, $this->session['CHAT_ID']); if ( $this->session['CLOSED'] == 'Y' || $this->session['SPAM'] == 'Y' || $this->session['WAIT_ACTION'] == 'Y' && $this->session['WAIT_ANSWER'] == 'N' ) { $update['WAIT_ACTION'] = 'N'; $update['WAIT_ANSWER'] = 'N'; $update['CLOSED'] = 'Y'; $params = [ "CLASS" => "bx-messenger-content-item-ol-end" ]; if ($this->config['VOTE_MESSAGE'] == 'Y') { $params["TYPE"] = "lines"; $params["COMPONENT_ID"] = "bx-imopenlines-message"; $params["IMOL_VOTE_SID"] = $this->session['ID']; $params["IMOL_VOTE_USER"] = $this->session['VOTE']; $params["IMOL_VOTE_HEAD"] = $this->session['VOTE_HEAD']; $params["IMOL_COMMENT_HEAD"] = $this->session['COMMENT_HEAD']; } { $addMessageId = Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "FROM_USER_ID" => $this->session['OPERATOR_ID'], "MESSAGE" => Loc::getMessage('IMOL_SESSION_CLOSE_FINAL'), "SYSTEM" => 'Y', "RECENT_ADD" => $userViewChat? 'Y': 'N', "PARAMS" => $params ]); if(!empty($addMessageId)) { $lastMessageId = $addMessageId; } } } else { $enableSystemMessage = $this->isEnableSendSystemMessage(); if ($this->config['ACTIVE'] == 'N') { $update['WAIT_ACTION'] = 'N'; $update['WAIT_ANSWER'] = 'N'; $update['CLOSED'] = 'Y'; $params = [ "CLASS" => "bx-messenger-content-item-ol-end" ]; if ($this->config['VOTE_MESSAGE'] == 'Y') { $params["TYPE"] = "lines"; $params["COMPONENT_ID"] = "bx-imopenlines-message"; $params["IMOL_VOTE_SID"] = $this->session['ID']; $params["IMOL_VOTE_USER"] = $this->session['VOTE']; $params["IMOL_VOTE_HEAD"] = $this->session['VOTE_HEAD']; $params["IMOL_COMMENT_HEAD"] = $this->session['COMMENT_HEAD']; } { $addMessageId = Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "FROM_USER_ID" => $this->session['OPERATOR_ID'], "RECENT_ADD" => $userViewChat? 'Y': 'N', "MESSAGE" => Loc::getMessage('IMOL_SESSION_CLOSE_FINAL'), "SYSTEM" => 'Y', "PARAMS" => $params ]); if(!empty($addMessageId)) { $lastMessageId = $addMessageId; } } } else if ($auto) { $waitAction = false; if ($enableSystemMessage && $this->config['AUTO_CLOSE_RULE'] == self::RULE_TEXT) { $this->chat->update([ Chat::getFieldName(Chat::FIELD_SILENT_MODE) => 'N' ]); $addMessageId = Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "FROM_USER_ID" => $this->session['OPERATOR_ID'], "MESSAGE" => $this->config['AUTO_CLOSE_TEXT'], "SYSTEM" => 'Y', "RECENT_ADD" => $userViewChat? 'Y': 'N', "IMPORTANT_CONNECTOR" => 'Y', "PARAMS" => [ "CLASS" => "bx-messenger-content-item-ol-output", "IMOL_FORM" => "history", "TYPE" => "lines", "COMPONENT_ID" => "bx-imopenlines-message", ] ]); if(!empty($addMessageId)) { $lastMessageId = $addMessageId; } $update['WAIT_ACTION'] = 'Y'; $update['WAIT_ANSWER'] = 'N'; $waitAction = true; } if ($enableSystemMessage && $this->config['VOTE_MESSAGE'] == 'Y' && $this->session['CHAT_ID'] && empty($this->session['VOTE'])) { $addMessageId = Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "FROM_USER_ID" => $this->session['OPERATOR_ID'], "MESSAGE" => $this->config['VOTE_MESSAGE_2_TEXT'], "SYSTEM" => 'Y', "RECENT_ADD" => $userViewChat? 'Y': 'N', "IMPORTANT_CONNECTOR" => 'Y', "PARAMS" => [ "IMOL_VOTE" => $this->session['ID'], "IMOL_VOTE_TEXT" => $this->config['VOTE_MESSAGE_1_TEXT'], "IMOL_VOTE_LIKE" => $this->config['VOTE_MESSAGE_1_LIKE'], "IMOL_VOTE_DISLIKE" => $this->config['VOTE_MESSAGE_1_DISLIKE'], "CLASS" => "bx-messenger-content-item-ol-output bx-messenger-content-item-vote", "IMOL_FORM" => "history-delay", "TYPE" => "lines", "COMPONENT_ID" => "bx-imopenlines-message", ] ]); if(!empty($addMessageId)) { $lastMessageId = $addMessageId; } $update['WAIT_ACTION'] = 'Y'; $update['WAIT_ANSWER'] = 'N'; $update['WAIT_VOTE'] = 'Y'; $waitAction = true; } if (!$waitAction) { $update['WAIT_ACTION'] = 'N'; $update['WAIT_ANSWER'] = 'N'; $update['CLOSED'] = 'Y'; $params = [ "CLASS" => "bx-messenger-content-item-ol-end" ]; if ($this->config['VOTE_MESSAGE'] == 'Y') { $params["TYPE"] = "lines"; $params["COMPONENT_ID"] = "bx-imopenlines-message"; $params["IMOL_VOTE_SID"] = $this->session['ID']; $params["IMOL_VOTE_USER"] = $this->session['VOTE']; $params["IMOL_VOTE_HEAD"] = $this->session['VOTE_HEAD']; $params["IMOL_COMMENT_HEAD"] = $this->session['COMMENT_HEAD']; } $addMessageId = Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "FROM_USER_ID" => $this->session['OPERATOR_ID'], "RECENT_ADD" => $userViewChat? 'Y': 'N', "MESSAGE" => Loc::getMessage('IMOL_SESSION_CLOSE_AUTO'), "SYSTEM" => 'Y', "PARAMS" => $params ]); if(!empty($addMessageId)) { $lastMessageId = $addMessageId; } } } else { $waitAction = false; if ($enableSystemMessage && $this->config['CLOSE_RULE'] == self::RULE_TEXT) { $addMessageId = Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "FROM_USER_ID" => $this->session['OPERATOR_ID'], "MESSAGE" => $this->config['CLOSE_TEXT'], "RECENT_ADD" => $userViewChat? 'Y': 'N', "SYSTEM" => 'Y', "IMPORTANT_CONNECTOR" => 'Y', "PARAMS" => [ "CLASS" => "bx-messenger-content-item-ol-output", "IMOL_FORM" => "history", "TYPE" => "lines", "COMPONENT_ID" => "bx-imopenlines-message", ] ]); if(!empty($addMessageId)) { $lastMessageId = $addMessageId; } $update['WAIT_ACTION'] = 'Y'; $update['WAIT_ANSWER'] = 'N'; $waitAction = true; } if ($enableSystemMessage && $this->config['VOTE_MESSAGE'] == 'Y' && empty($this->session['VOTE'])) { $addMessageId = Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "FROM_USER_ID" => $this->session['OPERATOR_ID'], "MESSAGE" => $this->config['VOTE_MESSAGE_2_TEXT'], "SYSTEM" => 'Y', "RECENT_ADD" => $userViewChat? 'Y': 'N', "IMPORTANT_CONNECTOR" => 'Y', "PARAMS" => [ "IMOL_VOTE" => $this->session['ID'], "IMOL_VOTE_TEXT" => $this->config['VOTE_MESSAGE_1_TEXT'], "IMOL_VOTE_LIKE" => $this->config['VOTE_MESSAGE_1_LIKE'], "IMOL_VOTE_DISLIKE" => $this->config['VOTE_MESSAGE_1_DISLIKE'], "CLASS" => "bx-messenger-content-item-ol-output bx-messenger-content-item-vote", "IMOL_FORM" => "history-delay", "TYPE" => "lines", "COMPONENT_ID" => "bx-imopenlines-message", ] ]); if(!empty($addMessageId)) { $lastMessageId = $addMessageId; } $update['WAIT_ACTION'] = 'Y'; $update['WAIT_ANSWER'] = 'N'; $update['WAIT_VOTE'] = 'Y'; $waitAction = true; } if (!$waitAction) { $userSkip = \Bitrix\Im\User::getInstance($this->chat->getData('OPERATOR_ID')); $params = [ "CLASS" => "bx-messenger-content-item-ol-end" ]; if ($this->config['VOTE_MESSAGE'] == 'Y') { $params["IMOL_VOTE_SID"] = $this->session['ID']; $params["IMOL_VOTE_USER"] = $this->session['VOTE']; $params["IMOL_VOTE_HEAD"] = $this->session['VOTE_HEAD']; $params["IMOL_COMMENT_HEAD"] = $this->session['COMMENT_HEAD']; } $addMessageId = Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "FROM_USER_ID" => $this->session['OPERATOR_ID'], "RECENT_ADD" => $userViewChat? 'Y': 'N', "MESSAGE" => Loc::getMessage('IMOL_SESSION_CLOSE_' . $userSkip->getGender(), ['#USER#' => '[USER=' . $userSkip->getId().'][/USER]']), "SYSTEM" => 'Y', "PARAMS" => $params ]); if(!empty($addMessageId)) { $lastMessageId = $addMessageId; } $update['WAIT_ACTION'] = 'N'; $update['WAIT_ANSWER'] = 'N'; $update['CLOSED'] = 'Y'; } if (!\Bitrix\Im\User::getInstance($this->session['OPERATOR_ID'])->isBot()) { $update['DATE_OPERATOR_CLOSE'] = $currentDate; } if ($this->session['DATE_CREATE']) { $update['TIME_CLOSE'] = $currentDate->getTimestamp()-$this->session['DATE_CREATE']->getTimestamp(); } } $update['DATE_MODIFY'] = $currentDate; } if ($update['CLOSED'] == 'Y') { if ($this->session['CRM_ACTIVITY_ID'] > 0) { $crmManager = new Crm($this); if($crmManager->isLoaded()) { $crmManager->setSessionClosed(['DATE_CLOSE' => $currentDate]); } } $update['DATE_CLOSE'] = $currentDate; if ($this->session['TIME_CLOSE'] <= 0 && $this->session['DATE_CREATE']) { $update['TIME_CLOSE'] = $update['DATE_CLOSE']->getTimestamp()-$this->session['DATE_CREATE']->getTimestamp(); } if (\Bitrix\Im\User::getInstance($this->session['OPERATOR_ID'])->isBot() && $this->session['TIME_BOT'] <= 0 && $this->session['DATE_CREATE']) { $update['TIME_BOT'] = $update['DATE_CLOSE']->getTimestamp()-$this->session['DATE_CREATE']->getTimestamp(); } if ($this->session['CHAT_ID']) { $update['END_ID'] = $lastMessageId; } } if ($hideChat) { Im::chatHide($this->session['CHAT_ID']); } $this->update($update); if (method_exists('\\Bitrix\\ImConnector\\Chat', 'deleteLastMessage')) { //TODO: Replace with the method \Bitrix\ImOpenLines\Chat::parseLinesChatEntityId or \Bitrix\ImOpenLines\Chat::parseLiveChatEntityId list($connectorId, $lineId, $connectorChatId, $connectorUserId) = explode('|', $this->user['USER_CODE']); \Bitrix\ImConnector\Chat::deleteLastMessage($connectorChatId, $connectorId); } if ($update['CLOSED'] == 'Y') { $eventData['RUNTIME_SESSION'] = $this; $eventData['SESSION'] = $this->session; $eventData['CONFIG'] = $this->config; $event = new \Bitrix\Main\Event("imopenlines", "OnSessionFinish", $eventData); $event->send(); } $result = true; } return $result; } /** * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function dismissedOperatorFinish() { if (empty($this->session)) { return false; } $update = []; $this->session['CLOSED'] = 'Y'; $update['FORCE_CLOSE'] = 'Y'; if(!empty($this->session['DATE_LAST_MESSAGE'])) { $closeDate = $this->session['DATE_LAST_MESSAGE']->add('60 MINUTES'); } else { $closeDate = new DateTime(); } if ($this->session['CHAT_ID']) { $chatData = \Bitrix\Im\Model\ChatTable::getById($this->session['CHAT_ID'])->fetch(); $lastMessageId = $chatData['LAST_MESSAGE_ID']; } else { $lastMessageId = 0; } $update['WAIT_ACTION'] = 'N'; $update['WAIT_ANSWER'] = 'N'; $update['WAIT_VOTE'] = 'N'; $update['CLOSED'] = 'Y'; if (!( $this->session['CLOSED'] == 'Y' || $this->session['SPAM'] == 'Y' || $this->session['WAIT_ACTION'] == 'Y' && $this->session['WAIT_ANSWER'] == 'N' )) { if ($this->config['ACTIVE'] != 'N') { if (!\Bitrix\Im\User::getInstance($this->session['OPERATOR_ID'])->isBot()) { $update['DATE_OPERATOR_CLOSE'] = $closeDate; } if ($this->session['DATE_CREATE']) { $update['TIME_CLOSE'] = $closeDate->getTimestamp()-$this->session['DATE_CREATE']->getTimestamp(); } } $update['DATE_MODIFY'] = $closeDate; } if ($this->session['CRM_ACTIVITY_ID'] > 0) { $crmManager = new Crm($this); if($crmManager->isLoaded()) { $crmManager->setSessionClosed(['DATE_CLOSE' => $closeDate]); } } $update['DATE_CLOSE'] = $closeDate; if ($this->session['TIME_CLOSE'] <= 0 && $this->session['DATE_CREATE']) { $update['TIME_CLOSE'] = $update['DATE_CLOSE']->getTimestamp()-$this->session['DATE_CREATE']->getTimestamp(); } if (\Bitrix\Im\User::getInstance($this->session['OPERATOR_ID'])->isBot() && $this->session['TIME_BOT'] <= 0 && $this->session['DATE_CREATE']) { $update['TIME_BOT'] = $update['DATE_CLOSE']->getTimestamp()-$this->session['DATE_CREATE']->getTimestamp(); } if ($this->session['CHAT_ID']) { $update['END_ID'] = $lastMessageId; } Im::chatHide($this->session['CHAT_ID']); //The data in the chat is not specially updated in order to avoid any notifications. $this->update($update); Debug::addSession($this, __METHOD__, ['update' => $update]); $this->addEventToLog(Library::EVENT_SESSION_DISMISSED_OPERATOR_FINISH, $update); return true; } public function getData($field = '') { if ($field) { return isset($this->session[$field])? $this->session[$field]: null; } else { return $this->session; } } public function getConfig($field = '') { if ($field) { return isset($this->config[$field])? $this->config[$field]: null; } else { return $this->config; } } public function getUser($field = '') { if ($field) { return isset($this->user[$field])? $this->user[$field]: null; } else { return $this->user; } } /** * @param $id * @param bool $waitAnswer * @param bool $autoMode * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function setOperatorId($id, $waitAnswer = false, $autoMode = false) { $this->update([ 'WAIT_ANSWER' => $waitAnswer? 'Y': 'N', 'OPERATOR_ID' => $id ]); Debug::addSession($this, __METHOD__, ['id' => $id, 'waitAnswer' => $waitAnswer, 'autoMode' => $autoMode]); return true; } /** * Session update. * * TODO: the DATE_MODIFY field serves as a trigger for automatic actions! * TODO: Required express refactor the method and change the approach. * * @param $fields * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function update($fields) { $updateCheckTable = []; $updateChatSession = []; $updateDateCrmClose = []; if (isset($fields['CONFIG_ID'])) { $configManager = new Config(); $config = $configManager->get($fields['CONFIG_ID']); if ($config) { $this->config = $config; } else { unset($fields['CONFIG_ID']); } } if (array_key_exists('SEND_NO_ANSWER_TEXT', $fields) && $fields['SEND_NO_ANSWER_TEXT'] == 'Y') { $updateCheckTable['DATE_NO_ANSWER'] = null; } if (array_key_exists('CHECK_DATE_CLOSE', $fields)) { $updateCheckTable['DATE_CLOSE'] = $fields['CHECK_DATE_CLOSE']; unset($fields['CHECK_DATE_CLOSE']); } else if (isset($fields['DATE_MODIFY']) && $fields['CLOSED'] != 'Y') { $dateCrmClose = new DateTime(); $dateCrmClose->add('1 DAY'); $dateCrmClose->add($this->getConfig('AUTO_CLOSE_TIME').' SECONDS'); $fullCloseTime = $this->getConfig('FULL_CLOSE_TIME'); /** var DateTime */ $dateClose = clone $fields['DATE_MODIFY']; //do not pause if ($this->session['PAUSE'] == 'N' || $fields['PAUSE'] == 'N') { if (isset($fields['USER_ID']) && \Bitrix\Im\User::getInstance($fields['USER_ID'])->isConnector()) { if ($this->session['VOTE_SESSION'] && ($this->session['WAIT_ACTION'] == 'Y' && $fields['WAIT_ACTION'] != 'N' || $fields['WAIT_ACTION'] == 'Y')) { $fields['STATUS'] = self::STATUS_WAIT_CLIENT; if(!empty($fullCloseTime)) { $dateClose->add($fullCloseTime . ' MINUTES'); } $updateDateCrmClose = $dateCrmClose; } else { $dateClose->add('1 MONTH'); $updateCheckTable['DATE_CLOSE'] = $dateClose; $updateChatSession['WAIT_ACTION'] = $this->session['WAIT_ACTION'] = $fields['WAIT_ACTION'] = "N"; if ($this->session['STATUS'] >= self::STATUS_OPERATOR || $this->session['STATUS'] == self::STATUS_ANSWER) { $updateDateCrmClose = $dateCrmClose; } if ($this->session['WAIT_ANSWER'] == 'N') { $fields['STATUS'] = $this->session['STATUS'] >= self::STATUS_OPERATOR? self::STATUS_CLIENT_AFTER_OPERATOR: self::STATUS_CLIENT; } } } else { if (isset($fields['SKIP_DATE_CLOSE'])) { $dateClose->add('1 MONTH'); } else if ($this->session['WAIT_ANSWER'] == 'Y' && $fields['WAIT_ANSWER'] != 'N' || $fields['WAIT_ANSWER'] == 'Y') { $fields['STATUS'] = $this->session['STATUS'] >= self::STATUS_CLIENT_AFTER_OPERATOR? self::STATUS_CLIENT_AFTER_OPERATOR: self::STATUS_CLIENT; $dateClose->add('1 MONTH'); if ($this->session['STATUS'] >= self::STATUS_OPERATOR) { $updateDateCrmClose = $dateCrmClose; } } else if ($this->session['WAIT_ACTION'] == 'Y' && $fields['WAIT_ACTION'] != 'N' || $fields['WAIT_ACTION'] == 'Y') { $fields['STATUS'] = self::STATUS_WAIT_CLIENT; if(!empty($fullCloseTime)) { $dateClose->add($fullCloseTime . ' MINUTES'); } $updateDateCrmClose = $dateCrmClose; } else { $fields['STATUS'] = self::STATUS_OPERATOR; $dateClose->add($this->config['AUTO_CLOSE_TIME'].' SECONDS'); $updateDateCrmClose = $dateCrmClose; } } } //On pause else { $dateCrmClose->add('6 DAY'); // 6+1 = 7 if ($this->session['WAIT_ACTION'] == 'N' && isset($fields['USER_ID']) && \Bitrix\Im\User::getInstance($fields['USER_ID'])->isConnector()) { $dateClose->add('1 MONTH'); if ($this->session['STATUS'] >= self::STATUS_OPERATOR || $this->session['STATUS'] == self::STATUS_ANSWER) { $updateDateCrmClose = $dateCrmClose; } if ($this->session['WAIT_ANSWER'] == 'N') { $fields['STATUS'] = $this->session['STATUS'] >= self::STATUS_OPERATOR? self::STATUS_CLIENT_AFTER_OPERATOR: self::STATUS_CLIENT; } } else { if (isset($fields['SKIP_DATE_CLOSE'])) { $dateClose->add('1 MONTH'); } else if ($this->session['WAIT_ANSWER'] == 'Y' && $fields['WAIT_ANSWER'] != 'N' || $fields['WAIT_ANSWER'] == 'Y') { $dateClose->add('1 MONTH'); $fields['STATUS'] = $this->session['STATUS'] >= self::STATUS_CLIENT_AFTER_OPERATOR? self::STATUS_CLIENT_AFTER_OPERATOR: self::STATUS_CLIENT; if ($this->session['STATUS'] >= self::STATUS_OPERATOR) { $updateDateCrmClose = $dateCrmClose; } } else if ($this->session['WAIT_ACTION'] == 'Y' && $fields['WAIT_ACTION'] != 'N' || $fields['WAIT_ACTION'] == 'Y') { $fields['STATUS'] = self::STATUS_WAIT_CLIENT; if(!empty($fullCloseTime)) { $dateClose->add($fullCloseTime . ' MINUTES'); } $updateDateCrmClose = $dateCrmClose; } else { $dateClose->add('1 MONTH'); $fields['STATUS'] = self::STATUS_OPERATOR; $updateDateCrmClose = $dateCrmClose; } } } if ($dateClose) { $updateCheckTable['DATE_CLOSE'] = $dateClose; } } if (isset($fields['DATE_LAST_MESSAGE']) && $this->session['DATE_CREATE']) { $fields['TIME_DIALOG'] = $fields['DATE_LAST_MESSAGE']->getTimestamp()-$this->session['DATE_CREATE']->getTimestamp(); } if (isset($fields['CLOSED']) && $fields['CLOSED'] == 'Y') { if ($this->session['SPAM'] == 'Y') { $fields['STATUS'] = self::STATUS_SPAM; $updateChatSession['ID'] = 0; } else { $fields['STATUS'] = self::STATUS_CLOSE; } $fields['PAUSE'] = 'N'; $updateChatSession['PAUSE'] = 'N'; $updateCheckTable = []; ConfigStatistic::getInstance($this->session['CONFIG_ID'])->addClosed()->deleteInWork(); if ($fields['FORCE_CLOSE'] != 'Y') { $this->chat->close(); } if (Connector::isLiveChat($this->session['SOURCE']) && $this->session['SPAM'] != 'Y') { if (Loader::includeModule('im') && \Bitrix\Im\User::getInstance($this->session['USER_ID'])->isOnline()) { \CAgent::AddAgent('\Bitrix\ImOpenLines\Mail::sendOperatorAnswerAgent('.$this->session['ID'].');', "imopenlines", "N", 60, "", "Y", \ConvertTimeStamp(time()+\CTimeZone::GetOffset()+60, "FULL")); } else { \Bitrix\ImOpenLines\Mail::sendOperatorAnswer($this->session['ID']); } } Model\SessionCheckTable::delete($this->session['ID']); } else if (isset($fields['PAUSE'])) { if ($fields['PAUSE'] == 'Y') { $datePause = new DateTime(); $datePause->add('1 WEEK'); $updateCheckTable['DATE_CLOSE'] = $datePause; $updateCheckTable['DATE_QUEUE'] = null; } } else if (isset($fields['WAIT_ANSWER'])) { if ($fields['WAIT_ANSWER'] == 'Y') { $fields['STATUS'] = self::STATUS_SKIP; $fields['PAUSE'] = 'N'; $updateChatSession['PAUSE'] = 'N'; $dateQueue = new DateTime(); //TODO: A bad place! Potential problem. Can change the distribution time logic by ignoring rules from the queue. $dateQueue->add($this->config['QUEUE_TIME'].' SECONDS'); $updateCheckTable['DATE_QUEUE'] = $dateQueue; } else { if ($this->session['STATUS'] < self::STATUS_ANSWER) { $fields['STATUS'] = self::STATUS_ANSWER; } $fields['WAIT_ACTION'] = isset($fields['WAIT_ACTION'])? $fields['WAIT_ACTION']: 'N'; $fields['PAUSE'] = 'N'; $updateChatSession['WAIT_ACTION'] = $fields['WAIT_ACTION']; $updateChatSession['PAUSE'] = 'N'; $updateCheckTable['DATE_QUEUE'] = null; } } if (!empty($updateChatSession)) { $this->chat->updateFieldData([Chat::FIELD_SESSION => $updateChatSession]); } if (isset($fields['MESSAGE_COUNT'])) { $fields["MESSAGE_COUNT"] = new SqlExpression("?# + 1", "MESSAGE_COUNT"); ConfigStatistic::getInstance($this->session['CONFIG_ID'])->addMessage(); } if (!empty($updateCheckTable)) { if ( isset($updateCheckTable['DATE_CLOSE']) && $this->session['CRM_ACTIVITY_ID'] > 0 && (!isset($fields['CLOSED']) || $fields['CLOSED'] == 'N') ) { if ( ($this->session['STATUS'] >= self::STATUS_ANSWER && !in_array($this->session['STATUS'], [self::STATUS_CLIENT, self::STATUS_CLIENT_AFTER_OPERATOR])) || ($fields['STATUS'] >= self::STATUS_ANSWER && !in_array($fields['STATUS'], [self::STATUS_CLIENT, self::STATUS_CLIENT_AFTER_OPERATOR])) ) { if ($updateCheckTable['DATE_CLOSE']) { $dateClose = clone $updateCheckTable['DATE_CLOSE']; } else { $dateClose = new Main\Type\DateTime(); } $dateClose->add($this->getConfig('AUTO_CLOSE_TIME').' SECONDS'); $dateClose->add('1 DAY'); $crmManager = new Crm($this); if($crmManager->isLoaded()) { $crmManager->setSessionDataClose($dateClose); } } } Model\SessionCheckTable::update($this->session['ID'], $updateCheckTable); } if (!empty($updateDateCrmClose) && $this->session['CRM_ACTIVITY_ID']) { $crmManager = new Crm($this); if($crmManager->isLoaded()) { $crmManager->setSessionDataClose($updateDateCrmClose); } } unset($fields['USER_ID']); unset($fields['SKIP_DATE_CLOSE']); unset($fields['FORCE_CLOSE']); if (isset($fields['STATUS']) && $this->session['STATUS'] != $fields['STATUS']) { $this->chat->updateSessionStatus($fields['STATUS']); if (Connector::isLiveChat($this->session['SOURCE'])) { $parsedUserCode = Session\Common::parseUserCode($this->session['USER_CODE']); } $sessionClose = false; if (isset($fields['CLOSED']) && $fields['CLOSED'] == 'Y') { $sessionClose = true; } \Bitrix\Pull\Event::add($this->session['USER_ID'], [ 'module_id' => 'imopenlines', 'command' => 'sessionStatus', 'params' => [ 'chatId' => (int)$parsedUserCode['EXTERNAL_CHAT_ID'], 'sessionId' => (int)$this->session['ID'], 'sessionStatus' => (int)$fields['STATUS'], 'spam' => $this->session['SPAM'] == 'Y', 'sessionClose' => $sessionClose ] ]); } foreach ($fields as $key => $value) { $this->session[$key] = $value; } foreach ($updateCheckTable as $key => $value) { $this->session['CHECK_'.$key] = $value; } if ($this->session['ID'] && !empty($fields)) { Model\SessionTable::update($this->session['ID'], $fields); } Debug::addSession($this, __METHOD__, ['fields' => $fields, 'updateCheckTable' => $updateCheckTable, 'updateChatSession' => $updateChatSession, 'updateDateCrmClose' => $updateDateCrmClose]); return true; } /** * @param $params * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function execAutoAction($params) { $update = []; if ($this->action == self::ACTION_CLOSED && $this->config['ACTIVE'] == 'N') { Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "MESSAGE" => Loc::getMessage('IMOL_SESSION_LINE_IS_CLOSED'), "SYSTEM" => 'Y', ]); } if ($this->chat->isNowCreated() && $this->config['AGREEMENT_MESSAGE'] == 'Y' && $this->isEnableSendSystemMessage()) { $addAgreementMessage = true; if (Connector::isLiveChat($this->session['SOURCE'])) { $parsedUserCode = Session\Common::parseUserCode($this->session['USER_CODE']); $addAgreementMessage = !\Bitrix\Main\UserConsent\Consent::getByContext(intval($this->config['AGREEMENT_ID']), 'imopenlines/livechat', $parsedUserCode['EXTERNAL_CHAT_ID']); } if ($addAgreementMessage) { $mess = Loc::loadLanguageFile(__FILE__, $this->config['LANGUAGE_ID']); Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "MESSAGE" => str_replace( ['#LINK_START#', '#LINK_END#'], ['[URL='.\Bitrix\ImOpenLines\Common::getAgreementLink($this->config['AGREEMENT_ID'], $this->config['LANGUAGE_ID'])."]", '[/URL]'], $mess['IMOL_SESSION_AGREEMENT_MESSAGE'] ), "SYSTEM" => 'Y', "IMPORTANT_CONNECTOR" => 'Y', "PARAMS" => [ "CLASS" => "bx-messenger-content-item-ol-output", ] ]); Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "MESSAGE" => Loc::getMessage('IMOL_SESSION_AGREEMENT_MESSAGE_OPERATOR'), "SYSTEM" => 'Y', "PARAMS" => [ "CLASS" => "bx-messenger-content-item-ol-attention", ] ]); } } if (is_object($GLOBALS['USER']) && method_exists($GLOBALS['USER'], 'GetId')) { $update['USER_ID'] = $GLOBALS['USER']->GetId(); } if($update) { $update['DATE_MODIFY'] = new DateTime(); $this->update($update); } } /** * Transfer to the next statement in the queue. * * @param bool $manual * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function transferToNextInQueue($manual = true) { $result = false; Debug::addSession($this, __METHOD__, ['manual' => $manual]); $queueManager = Queue::initialization($this); if($queueManager) { $result = $queueManager->transferToNext($manual); } return $result; } /** * Send notification about unavailability of the operator. * * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function sendMessageNoAnswer() { $result = false; if ($this->config['NO_ANSWER_RULE'] == Session::RULE_TEXT && $this->session['SEND_NO_ANSWER_TEXT'] != 'Y' && $this->isEnableSendSystemMessage()) { Im::addMessage([ "TO_CHAT_ID" => $this->session['CHAT_ID'], "MESSAGE" => $this->config['NO_ANSWER_TEXT'], "SYSTEM" => 'Y', "IMPORTANT_CONNECTOR" => 'Y', "NO_SESSION_OL" => 'Y', "PARAMS" => [ "CLASS" => "bx-messenger-content-item-ol-output", "IMOL_FORM" => "offline", "TYPE" => "lines", "COMPONENT_ID" => "bx-imopenlines-message", ] ]); } if($this->session['SEND_NO_ANSWER_TEXT'] != 'Y') { $this->update(['SEND_NO_ANSWER_TEXT' => 'Y', 'WAIT_ACTION' => 'Y']); } else { $this->update(['SEND_NO_ANSWER_TEXT' => 'Y']); } Debug::addSession($this, __METHOD__, ['result' => $result]); return $result; } private static function prolongDueChatActivity($chatId) { $orm = Model\SessionTable::getList([ 'select' => [ 'ID', 'CHECK_DATE_CLOSE' => 'CHECK.DATE_CLOSE' ], 'filter' => [ '=CHAT_ID' => $chatId, '=CLOSED' => 'N' ] ]); if ($result = $orm->fetch()) { $currentDate = new DateTime(); if ($result['CHECK_DATE_CLOSE'] && $currentDate->getTimestamp()+600 > $result['CHECK_DATE_CLOSE']->getTimestamp()) { $dateClose = $result['CHECK_DATE_CLOSE']->add('10 MINUTES'); Model\SessionCheckTable::update($result['ID'], [ 'DATE_CLOSE' => $dateClose ]); } } } public static function setQueueFlagCache($type = "") { if (!$type) return false; $app = Application::getInstance(); $managedCache = $app->getManagedCache(); $managedCache->clean("imol_queue_flag_".$type); $managedCache->read(86400*30, "imol_queue_flag_".$type); $managedCache->set("imol_queue_flag_".$type, true); return true; } public static function deleteQueueFlagCache($type = "") { $app = Application::getInstance(); $managedCache = $app->getManagedCache(); if ($type) { $managedCache->clean("imol_queue_flag_".$type); } else { $managedCache->clean("imol_queue_flag_".self::CACHE_CLOSE); $managedCache->clean("imol_queue_flag_".self::CACHE_QUEUE); $managedCache->clean("imol_queue_flag_".self::CACHE_INIT); $managedCache->clean("imol_queue_flag_".self::CACHE_MAIL); $managedCache->clean("imol_queue_flag_".self::CACHE_NO_ANSWER); } return true; } /** * @param string $type * @return bool * @throws Main\SystemException */ public static function getQueueFlagCache($type = "") { if (!$type) return false; $app = Application::getInstance(); $managedCache = $app->getManagedCache(); if ($result = $managedCache->read(86400*30, "imol_queue_flag_".$type)) { $result = $managedCache->get("imol_queue_flag_".$type) === false? false: true; } return $result; } public function getChat() { return $this->chat; } public function getAction() { return $this->action; } /** * Remove all signs of automatic actions. * * @return bool */ public function resetActionAll(): bool { $this->action = self::ACTION_NONE; return true; } /** * To add users to the chat. * * @return bool * @throws Main\LoaderException */ public function joinUser() { Debug::addSession($this, __METHOD__, ['joinUserList' => $this->joinUserList]); if (!empty($this->joinUserList)) { $operatorFromCrm = false; if($this->isNowCreated()) { $operatorFromCrm = $this->session['OPERATOR_FROM_CRM'] == 'Y'? true : false; } $this->chat->sendJoinMessage($this->joinUserList, $operatorFromCrm); $this->chat->join($this->joinUserList); } return true; } public function isNowCreated() { return $this->isCreated; } /** * @param $fields * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function updateCrmFlags($fields) { $result = false; $updateFields = []; if( (isset($fields['CRM_CREATE_LEAD']) && $fields['CRM_CREATE_LEAD'] == 'Y') || (isset($fields['CRM_CREATE_COMPANY']) && $fields['CRM_CREATE_COMPANY'] == 'Y') || (isset($fields['CRM_CREATE_CONTACT']) && $fields['CRM_CREATE_CONTACT'] == 'Y') || (isset($fields['CRM_CREATE_DEAL']) && $fields['CRM_CREATE_DEAL'] == 'Y') || (isset($fields['CRM_ACTIVITY_ID']) && !empty($fields['CRM_ACTIVITY_ID'])) ) { $updateFields['CRM'] = 'Y'; $updateFields['CRM_CREATE'] = 'Y'; } elseif((isset($fields['CRM_ACTIVITY_ID']) && !empty($fields['CRM_ACTIVITY_ID']))) { $updateFields['CRM'] = 'Y'; } else { if(isset($fields['CRM_CREATE'])) { if($fields['CRM_CREATE'] == 'Y') { $updateFields['CRM_CREATE'] = 'Y'; $updateFields['CRM'] = 'Y'; } else { $updateFields['CRM_CREATE'] = 'N'; if(isset($fields['CRM'])) { if($fields['CRM'] == 'Y') { $updateFields['CRM'] = 'Y'; } else { $updateFields['CRM'] = 'N'; } } } } } if(isset($fields['CRM_CREATE_LEAD'])) { if($fields['CRM_CREATE_LEAD'] == 'Y') { $updateFields['CRM_CREATE_LEAD'] = 'Y'; } else { $updateFields['CRM_CREATE_LEAD'] = 'N'; } } if(isset($fields['CRM_CREATE_COMPANY'])) { if($fields['CRM_CREATE_COMPANY'] == 'Y') { $updateFields['CRM_CREATE_COMPANY'] = 'Y'; } else { $updateFields['CRM_CREATE_COMPANY'] = 'N'; } } if(isset($fields['CRM_CREATE_CONTACT'])) { if($fields['CRM_CREATE_CONTACT'] == 'Y') { $updateFields['CRM_CREATE_CONTACT'] = 'Y'; } else { $updateFields['CRM_CREATE_CONTACT'] = 'N'; } } if(isset($fields['CRM_CREATE_DEAL'])) { if($fields['CRM_CREATE_DEAL'] == 'Y') { $updateFields['CRM_CREATE_DEAL'] = 'Y'; } else { $updateFields['CRM_CREATE_DEAL'] = 'N'; } } if(isset($fields['CRM_ACTIVITY_ID'])) { $updateFields['CRM_ACTIVITY_ID'] = $fields['CRM_ACTIVITY_ID']; } if(!empty($updateFields)) { foreach ($updateFields as $cell=>$field) { if($this->getData($cell) == $field) { unset($updateFields['$cell']); } } } if(!empty($updateFields)) { $result = $this->update($updateFields); } Debug::addSession($this, __METHOD__, ['updateFields' => $updateFields, 'fields' => $fields]); return $result; } /** * The vote of the user via a special form. * * @param $sessionId * @param $action * @param null $userId * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public static function voteAsUser($sessionId, $action, $userId = null) { $finishSession = false; $sessionData = Model\SessionTable::getByIdPerformance($sessionId)->fetch(); if (!$sessionData) return false; $userId = intval($userId); if ($userId > 0 && $sessionData['USER_ID'] != $userId) { return false; } $voteValue = $action == 'dislike'? 1: 5; $session = new Session(); $result = $session->load([ 'USER_CODE' => $sessionData['USER_CODE'], 'SKIP_CREATE' => 'Y', 'DEFERRED_JOIN' => 'Y', 'VOTE_SESSION' => 'Y' ]); if (!$result) { return false; }; Debug::addSession($session, __METHOD__, ['sessionId' => $sessionId, 'action' => $action, 'userId' => $userId]); if ($session->session['ID'] != $sessionId) { return false; }; $updateSession['VOTE'] = $voteValue; $updateSession['WAIT_VOTE'] = 'N'; if ($session->getData('CLOSED') == 'Y' && $session->getData('VOTE') === '') { return false; } else if ($session->getData('WAIT_VOTE') == 'Y') { if($session->getConfig('VOTE_CLOSING_DELAY') == 'Y') { $finishSession = true; } } $session->update($updateSession); $voteEventParams = [ 'SESSION_DATA' => $sessionData, 'VOTE' => $voteValue, ]; $event = new Main\Event('imopenlines', 'OnSessionVote', $voteEventParams); $event->send(); if ($sessionData['END_ID'] > 0) { \CIMMessageParam::Set($sessionData['END_ID'], ['IMOL_VOTE_SID' => $sessionId, 'IMOL_VOTE_USER' => $voteValue]); \CIMMessageParam::SendPull($sessionData['END_ID'], ['IMOL_VOTE_SID', 'IMOL_VOTE_USER']); } if (Connector::isLiveChat($session->getData('SOURCE'))) { // TODO change to send message to chat \Bitrix\ImOpenLines\Chat::sendRatingNotify( \Bitrix\ImOpenLines\Chat::RATING_TYPE_CLIENT, $sessionData['ID'], $voteValue, $sessionData['OPERATOR_ID'], $sessionData['USER_ID'] ); } else { \Bitrix\ImOpenLines\Chat::sendRatingNotify( \Bitrix\ImOpenLines\Chat::RATING_TYPE_CLIENT, $sessionData['ID'], $voteValue, $sessionData['OPERATOR_ID'], $sessionData['USER_ID'] ); } if($finishSession === true) { $session->finish(true); } return true; } /** * @param $sessionId * @param null $voteValue * @param null $commentValue * @param null $userId * @return bool * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public static function voteAsHead($sessionId, $voteValue = null, $commentValue = null, $userId = null) { $result = false; $sessionData = Model\SessionTable::getByIdPerformance($sessionId)->fetch(); if ($sessionData) { $userId = intval($userId); if ($userId > 0) { $configManager = new \Bitrix\ImOpenLines\Config(); $resultPermissions = $configManager->canVoteAsHead($sessionData['CONFIG_ID']); } else { $resultPermissions = true; $userId = $GLOBALS['USER']->GetId(); } if($resultPermissions) { $fieldsUpdate = []; $pullMessage = [ 'module_id' => 'imopenlines', 'command' => 'voteHead', 'expiry' => 60, 'params' => [ 'sessionId' => $sessionId, ], ]; if(!empty($commentValue)) { if(strlen($commentValue) > 10000) { $commentValue = substr($commentValue, 0, 10000) . '...'; } $commentValueSafely = htmlspecialcharsbx($commentValue); } if($voteValue !== null && $commentValue !== null) { $voteValue = $voteValue == 1 || $voteValue <= 5? $voteValue: 0; $fieldsUpdate['VOTE_HEAD'] = $voteValue; $fieldsUpdate['COMMENT_HEAD'] = $commentValue; if($voteValue > 0) { \Bitrix\ImOpenLines\Chat::sendRatingNotify(\Bitrix\ImOpenLines\Chat::RATING_TYPE_HEAD_AND_COMMENT, $sessionData['ID'], ['vote' => $voteValue, 'comment' => $commentValue], $sessionData['OPERATOR_ID'], $userId); } else { \Bitrix\ImOpenLines\Chat::sendRatingNotify(\Bitrix\ImOpenLines\Chat::RATING_TYPE_COMMENT, $sessionData['ID'], $commentValue, $sessionData['OPERATOR_ID'], $userId); } $result = true; } elseif($voteValue !== null) { $voteValue = $voteValue == 1 || $voteValue <= 5? $voteValue: 0; $fieldsUpdate['VOTE_HEAD'] = $voteValue; if ($voteValue > 0) { \Bitrix\ImOpenLines\Chat::sendRatingNotify(\Bitrix\ImOpenLines\Chat::RATING_TYPE_HEAD, $sessionData['ID'], $voteValue, $sessionData['OPERATOR_ID'], $userId); } $result = true; } elseif($commentValue !== null) { $fieldsUpdate['COMMENT_HEAD'] = $commentValue; \Bitrix\ImOpenLines\Chat::sendRatingNotify(\Bitrix\ImOpenLines\Chat::RATING_TYPE_COMMENT, $sessionData['ID'], $commentValue, $sessionData['OPERATOR_ID'], $userId); $result = true; } if(!empty($fieldsUpdate)) { Model\SessionTable::update($sessionId, $fieldsUpdate); } if (Loader::includeModule("pull") && ($voteValue !==null || $commentValue !==null)) { $paramsPull = [ 'IMOL_VOTE_SID' => $sessionData['ID'] ]; if($voteValue !==null) { $pullMessage['params']['voteValue'] = $voteValue; $paramsPull['IMOL_VOTE_HEAD'] = $voteValue; } if($commentValue !==null) { $pullMessage['params']['commentValue'] = $commentValueSafely; $paramsPull['IMOL_COMMENT_HEAD']['text'] = $commentValueSafely; } $pullUsers = \CIMChat::GetRelationById($sessionData['CHAT_ID']); $pullUsers[] = $userId; \Bitrix\Pull\Event::add($pullUsers, $pullMessage); if($voteValue !==null) { $pullMessage['skip_users'] = $pullUsers; unset($pullMessage['params']['commentValue']); \CPullWatch::AddToStack('IMOL_STATISTICS', $pullMessage); } if ($sessionData['END_ID'] > 0) { \CIMMessageParam::Set($sessionData['END_ID'], $paramsPull); \CIMMessageParam::SendPull($sessionData['END_ID'], array_keys($paramsPull)); } } } } return $result; } /** * Closed sessions, which for some reason remained open in the presence of an actual and active session. * * @param $duplicateSession * @param $actualSession * @return Result * @throws \Exception */ protected static function closeDuplicate($duplicateSession, $actualSession) { $result = new Result(); $resultSessionUpdate = Model\SessionTable::update($duplicateSession['ID'], [ 'STATUS' => self::STATUS_DUPLICATE, 'WAIT_ANSWER' => 'N', 'CLOSED' => 'Y' ]); if(!$resultSessionUpdate->isSuccess()) { $result->addErrors($resultSessionUpdate->getErrors()); } $resultSessionCheckDelete = Model\SessionCheckTable::delete($duplicateSession['ID']); if(!$resultSessionCheckDelete->isSuccess()) { $result->addErrors($resultSessionCheckDelete->getErrors()); } if ( $actualSession['CHAT_ID'] != $duplicateSession['CHAT_ID'] || $actualSession['OPERATOR_ID'] && $duplicateSession['OPERATOR_ID'] && $actualSession['OPERATOR_ID'] != $duplicateSession['OPERATOR_ID'] ) { $chatManager = new Chat($duplicateSession['CHAT_ID']); $chatManager->leave($duplicateSession['OPERATOR_ID']); } //statistics ConfigStatistic::getInstance($duplicateSession['CONFIG_ID'])->addClosed()->deleteInWork(); //statistics END return $result; } /** * Checks that message is first operator message in current session * * @param $messageId * @return bool * @throws Main\ArgumentException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function isFirstOperatorMessage($messageId) { $message = \Bitrix\Im\MessageTable::getList( [ 'select' => ['ID'], 'order' => ['ID' => 'ASC'], 'filter' => [ 'CHAT.ENTITY_ID' => $this->getData('USER_CODE'), 'CHAT.ENTITY_TYPE' => \Bitrix\Im\Alias::ENTITY_TYPE_OPEN_LINE, 'AUTHOR_ID' => $this->getData('OPERATOR_ID'), '>ID' => $this->getData('START_ID') ] ] )->fetch(); return $message['ID'] == $messageId; } /** * Add new event item to event log table. * * @param string $eventType * @param Main\Result|array|null $result * * @return Main\ORM\Data\AddResult|Main\Result|mixed * @throws \Exception */ private function addEventToLog($eventType, $result = null) { if (is_null($result)) { $result = new Result(); } else if(!($result instanceof Result)) { $resultData = $result; $result = new Result(); $result->setData($resultData); } $resultData = []; $fieldData = $result->getData(); if (is_array($fieldData) && !empty($fieldData)) { $resultData = array_merge($resultData, $fieldData); } $result->setData($resultData); $eventLog = EventLog::addEvent($eventType, $result, $this->config['ID'], $this->session['ID']); return $eventLog; } /** * Check whether system messages can be sent to the session. * * @return bool */ public function isEnableSendSystemMessage(): bool { $result = false; if(!empty($this->connectorId)) { $result = Connector::isEnableSendSystemMessage($this->connectorId); } if($result) { if($this->action == self::ACTION_CLOSED && $this->config['ACTIVE'] == 'N') { $result = false; } } if (ReplyBlock::isBlocked($this)) { $result = false; } return $result; } //Event public static function onSessionProlongLastMessage($chatId, $dialogId, $entityType = '', $entityId = '', $userId = '') { if ($entityType != 'LINES') return true; self::prolongDueChatActivity($chatId); return true; } public static function onSessionProlongWriting($params) { if ($params['CHAT']['ENTITY_TYPE'] != 'LINES') return true; self::prolongDueChatActivity($params['CHAT']['ID']); return true; } public static function onSessionProlongChatRename($chatId, $title, $entityType = '', $entityId = '', $userId = '') { if ($entityType != 'LINES') return true; self::prolongDueChatActivity($chatId); return true; } //Agent /** * @deprecated * * @param $nextExec * @param $offset * @return string * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public static function transferToNextInQueueAgent($nextExec, $offset = 0) { return Agent::transferToNextInQueue($nextExec, $offset); } /** * @deprecated * * @param $nextExec * @return string * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public static function closeByTimeAgent($nextExec) { return Agent::closeByTime($nextExec); } /** * @deprecated * * @param $nextExec * @return string * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public static function mailByTimeAgent($nextExec) { return Agent::mailByTime($nextExec); } /** * @deprecated * * @return array */ public static function getAgreementFields() { return Session\Common::getAgreementFields(); } /** * Delete all work data about session with sessionId * * @param $sessionId * * @return bool * @throws Main\ArgumentException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public static function deleteSession($sessionId) { //TODO - add removing of bounded im_chat SessionTable::delete($sessionId); SessionCheckTable::delete($sessionId); SessionIndexTable::delete($sessionId); $kpi = new KpiManager($sessionId); $kpi->deleteSessionMessages(); unset($kpi); return true; } /** * Adds a lock to the session and chat. * * @param int $sessionId * @param Chat $chat * @param array $limit * @throws Main\ArgumentException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public static function setReplyBlock(int $sessionId, Chat $chat , array $limit): void { if (!empty($limit['BLOCK_DATE']) && !empty($limit['BLOCK_REASON'])) { Model\SessionTable::update($sessionId, Array( 'BLOCK_DATE' => $limit['BLOCK_DATE'], 'BLOCK_REASON' => $limit['BLOCK_REASON'], )); $chat->updateFieldData([Chat::FIELD_SESSION => [ 'ID' => $sessionId, 'BLOCK_DATE' => $limit['BLOCK_DATE'], 'BLOCK_REASON' => $limit['BLOCK_REASON'], ]]); } } /** * Removes a block from the session and chat. * * @param int $sessionId * @param Chat $chat * @throws Main\ArgumentException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public static function deleteReplyBlock(int $sessionId, Chat $chat): void { if ($sessionId > 0 && $chat) { Model\SessionTable::update($sessionId, Array( 'BLOCK_DATE' => null, 'BLOCK_REASON' => null, )); $chat->updateFieldData([Chat::FIELD_SESSION => [ 'ID' => $sessionId, 'BLOCK_DATE' => 0, 'BLOCK_REASON' => '', ]]); } } /** * Checks if the ability to respond is blocked. * * @return bool * @throws Main\ObjectException */ public function isReplyBlocked(): bool { $sessionData = $this->getData(); if (!empty($sessionData['BLOCK_DATE'])) { if ($sessionData['BLOCK_DATE'] < new Main\Type\DateTime()) { return true; } } return false; } /** * @deprecated * * @param $nextExec * @return string */ public static function dismissedOperatorAgent($nextExec) { return ''; } }
/var/www/axolotl/data/www/kirov.axolotls.ru/bitrix/modules/imopenlines/lib/session.php