• Модуль: imopenlines
  • Путь к файлу: ~/bitrix/modules/imopenlines/lib/connector.php
  • Класс: BitrixImOpenLinesConnector
  • Вызов: Connector::addMessage
public function addMessage($params)
{
	$result = false;
	$finishSession = false;
	$voteSession = false;

	if (!empty($params))
	{
		if (
			!in_array($params['connector']['connector_id'], self::$noVote)
			&&
			(
				mb_strpos($params['message']['text'], '1') === 0
				|| mb_strpos($params['message']['text'], '0') === 0
			)
			&&
			(
				mb_strlen(trim($params['message']['text'])) == 1
				|| mb_substr($params['message']['text'], 1, 1) == " "
			)
		)
		{
			$voteSession = true;
		}

		$addMessage = [
			"FROM_USER_ID" => $params['message']['user_id'],
			"PARAMS" => $params['message']['params'] ?? []
			//"SKIP_COMMAND" => "Y"
		];
		//if (is_object($params['message']['date']))
		//{
		//	$addMessage["MESSAGE_DATE"] = $params['message']['date']->toString();
		//}
		if (!empty($params['message']['text']) || $params['message']['text'] === '0')
		{
			$addMessage["MESSAGE"] = $params['message']['text'];
		}

		if (!empty($params['message']['attach']))
		{
			if ($params['connector']['connector_id'] == self::TYPE_LIVECHAT)
			{
				$addMessage["ATTACH"] = $params['message']['attach'];
			}
			else
			{
				$addMessage["ATTACH"] = CIMMessageParamAttach::GetAttachByJson($params['message']['attach']);
			}
		}
		if (!empty($params['message']['keyboard']))
		{
			if ($params['connector']['connector_id'] == self::TYPE_LIVECHAT)
			{
				$addMessage["KEYBOARD"] = $params['message']['keyboard'];
			}
			else
			{
				$keyboard = [];
				if (!isset($params['message']['keyboard']['BUTTONS']))
				{
					$keyboard['BUTTONS'] = $params['message']['keyboard'];
				}
				else
				{
					$keyboard = $params['message']['keyboard'];
				}
				$addMessage["KEYBOARD"] = Keyboard::getKeyboardByJson($keyboard);
			}
		}
		if (!empty($params['message']['fileLinks']))
		{
			if (!$addMessage["ATTACH"])
			{
				$addMessage["ATTACH"] = new CIMMessageParamAttach(null, CIMMessageParamAttach::CHAT);
			}

			foreach ($params['message']['fileLinks'] as $key => $value)
			{
				if ($value['type'] === 'image')
				{
					$addMessage["ATTACH"]->AddImages([[
						"NAME" => $value['name'],
						"LINK" => $value['link'],
						"WIDTH" => (int)$value['width'],
						"HEIGHT" => (int)$value['height'],
					]]);
				}
				else
				{
					$addMessage["ATTACH"]->AddFiles([[
						"NAME" => $value['name'],
						"LINK" => $value['link'],
						"SIZE" => $value['size'],
					]]);
				}
			}
		}

		$userCode = self::getUserCode($params['connector']);
		$keyLock = Chat::PREFIX_KEY_LOCK_NEW_SESSION . $userCode;

		$iteration = 0;
		$isAddMessage = false;
		do
		{
			$iteration++;
			if (
				$iteration > self::LOCK_MAX_ITERATIONS
				|| ToolsLock::getInstance()->set($keyLock)
			)
			{
				if (
					!empty($params['message']['files'])
					|| !empty($addMessage['ATTACH'])
					|| $addMessage['MESSAGE'] <> ''
				)
				{
					$userViewChat = false;
					$addVoteResult = false;

					$session = new Session();
					$resultLoadSession = $session->load([
						'USER_CODE' => self::getUserCode($params['connector']),
						'CRM_SKIP_PHONE_VALIDATE' => ($params['extra']['skip_phone_validate'] ?? ''),
						//TODO: ??
						'CONNECTOR' => $params,
						'DEFERRED_JOIN' => 'Y',
						'VOTE_SESSION' => $voteSession? 'Y': 'N'
					]);
					if (
						$resultLoadSession ||
						$session->isCloseVote()
					)
					{
						$addMessage["TO_CHAT_ID"] = $session->getData('CHAT_ID');
						if (!empty($params['message']['files']))
						{
							$params['message']['files'] = CIMDisk::UploadFileFromMain(
								$session->getData('CHAT_ID'),
								$params['message']['files']
							);

							if ($params['message']['files'])
							{
								$addMessage["PARAMS"]['FILE_ID'] = $params['message']['files'];
							}
							else if ($addMessage["MESSAGE"] == '' && empty($addMessage["ATTACH"]))
							{
								$addMessage["MESSAGE"] = '[FILE]';
							}
						}
					}

					if ($resultLoadSession)
					{
						if ($session->isNowCreated())
						{
							$customDataMessage = '';
							$customDataAttach = null;

							$customData = ImOpenLinesWidgetCache::get($params['connector']['user_id'], 'CUSTOM_DATA');
							if ($customData)
							{
								$customDataAttach = CIMMessageParamAttach::GetAttachByJson($customData);
								if ($customDataAttach && $customDataAttach->IsEmpty())
								{
									$customDataAttach = null;
								}
								else
								{
									$customDataMessage = '[B]'.Loc::getMessage('IMOL_CONNECTOR_RECEIVED_DATA').'[/B]';
								}
							}
							else // TODO remove this after delete old livechat - see ImOpenLinesConnector::saveCustomData
							{
								if ($params['connector']['connector_id'] == self::TYPE_LIVECHAT)
								{
									$orm = ChatTable::getById($params['chat']['id']);
									$guestChatData = $orm->fetch();
								}
								else
								{
									$guestChatData = $session->getChat()->getData();
								}

								if ($guestChatData && $guestChatData['DESCRIPTION'] <> '')
								{
									$customDataMessage = '[B]'.Loc::getMessage('IMOL_CONNECTOR_RECEIVED_DATA').'[/B][BR] '.$guestChatData['DESCRIPTION'];
								}
							}

							if ($params['connector']['connector_id'] == self::TYPE_LIVECHAT)
							{
								$chat = new Chat($params['chat']['id']);
								$chat->updateFieldData([Chat::FIELD_LIVECHAT => [
									'SESSION_ID' => $session->getData('ID'),
									'SHOW_FORM' => 'Y'
								]]);
							}

							if ($customDataMessage)
							{
								Im::addMessage([
									'TO_CHAT_ID' => $session->getData('CHAT_ID'),
									'MESSAGE' => $customDataMessage,
									'ATTACH' => $customDataAttach,
									'SYSTEM' => 'Y',
									'SKIP_COMMAND' => 'Y',
									'PARAMS' => [
										'CLASS' => 'bx-messenger-content-item-system'
									],
								]);
							}
						}

						if (!empty($params['message']['description']))
						{
							Im::addMessage([
								'TO_CHAT_ID' => $session->getData('CHAT_ID'),
								'MESSAGE' => $params['message']['description'],
								'SYSTEM' => 'Y',
								'SKIP_COMMAND' => 'Y',
								'URL_PREVIEW' => 'N',
								'PARAMS' => [
									'CLASS' => 'bx-messenger-content-item-system'
								],
							]);
							unset($params['message']['description']);
						}

						$session->joinUser();

						if ($session->getData('OPERATOR_ID') > 0)
						{
							$userViewChat = CIMContactList::InRecent($session->getData('OPERATOR_ID'), IM_MESSAGE_OPEN_LINE, $session->getData('CHAT_ID'));
						}
						else
						{
							$userViewChat  = false;
						}

						if (
							$voteSession &&
							$session->getData('WAIT_VOTE') == 'Y'
						)
						{
							$voteValue = 0;
							if (mb_strlen($addMessage["MESSAGE"]) > 1)
							{
								$userViewChat = true;
							}
							if (mb_strpos($addMessage["MESSAGE"], '1') === 0)
							{
								$voteValue = 5;
								$addMessage["MESSAGE"] = '[like]'.mb_substr($addMessage["MESSAGE"], 1);
								$addVoteResult = $session->getConfig('VOTE_MESSAGE_2_LIKE');
							}
							else if (mb_strpos($addMessage["MESSAGE"], '0') === 0)
							{
								$voteValue = 1;
								$addMessage["MESSAGE"] = '[dislike]'.mb_substr($addMessage["MESSAGE"], 1);
								$addVoteResult = $session->getConfig('VOTE_MESSAGE_2_DISLIKE');
							}
							if ($addVoteResult)
							{
								$voteEventParams = [
									'SESSION_DATA' => $session->getData(),
									'VOTE' => $voteValue,
								];
								$event = new Event('imopenlines', 'OnSessionVote', $voteEventParams);
								$event->send();

								$addMessage['RECENT_ADD'] = $userViewChat? 'Y': 'N';
								$session->update(['VOTE' => $voteValue, 'WAIT_VOTE' => 'N']);

								if ($session->getConfig('VOTE_CLOSING_DELAY') == 'Y')
								{
									$finishSession = true;
								}

								Chat::sendRatingNotify(Chat::RATING_TYPE_CLIENT, $session->getData('ID'), $voteValue, $session->getData('OPERATOR_ID'), $session->getData('USER_ID'));
							}
						}
						else
						{
							$voteSession = false;
						}
					}

					if (
						$resultLoadSession ||
						$session->isCloseVote()
					)
					{
						$event = new Event('imopenlines', self::EVENT_IMOPENLINE_MESSAGE_RECEIVE, $addMessage);
						$event->send();

						$eventMessageFields = $event->getParameters();
						if (!empty($eventMessageFields['MESSAGE']))
						{
							$addMessage['MESSAGE'] = $eventMessageFields['MESSAGE'];
						}
						if (!empty($eventMessageFields['PARAMS']))
						{
							$addMessage['PARAMS'] = $eventMessageFields['PARAMS'];
						}

						$messageId = Im::addMessage($addMessage);
					}

					if (
						$resultLoadSession &&
						!empty($messageId)
					)
					{
						$isGroupChatAllowed = BitrixImConnectorConnector::isChatGroup($params['connector']['connector_id']) != true;

						if (
							$addMessage["MESSAGE"]
							&& (empty($params['extra']['disable_tracker']) || $params['extra']['disable_tracker'] !== 'Y')
							&& $isGroupChatAllowed
						)
						{
							$tracker = new ImOpenLinesTracker();
							$tracker
								->setSession($session)
								->trackMessage([
									'ID' => $messageId,
									'TEXT' => $addMessage["MESSAGE"]
								])
							;
						}
						if ($params['message']['id'])
						{
							if ($params['connector']['connector_id'] == self::TYPE_LIVECHAT)
							{
								if ($session->isNowCreated())
								{
									$updateParams = [
										'CONNECTOR_MID' => $messageId,
										'IMOL_SID' => $session->getData('ID'),
										'IMOL_FORM' => 'welcome',
										'TYPE' => 'lines',
										'COMPONENT_ID' => 'bx-imopenlines-message',
									];
								}
								else
								{
									$updateParams = [
										'CONNECTOR_MID' => $messageId,
									];
								}
								CIMMessageParam::Set($params['message']['id'], $updateParams);
								CIMMessageParam::SendPull($params['message']['id'], array_keys($updateParams));

								ImOpenLinesMail::removeSessionFromMailQueue($session->getData('ID'), false);
								Session::setLastSendMailId($session->getData(), $params['message']['id']);
							}

							CIMMessageParam::Set($messageId, ['CONNECTOR_MID' => $params['message']['id']]);
							if (!in_array($params['connector']['connector_id'], [self::TYPE_LIVECHAT, self::TYPE_NETWORK]))
							{
								CIMMessageParam::SendPull($messageId, ['CONNECTOR_MID']);
							}
						}

						if ($addVoteResult)
						{
							Im::addMessage([
								"TO_CHAT_ID" => $session->getData('CHAT_ID'),
								"MESSAGE" => $addVoteResult,
								"SYSTEM" => 'Y',
								"IMPORTANT_CONNECTOR" => 'Y',
								'NO_SESSION_OL' => 'Y',
								"PARAMS" => [
									"CLASS" => "bx-messenger-content-item-ol-output"
								],
								"RECENT_ADD" => $userViewChat? 'Y': 'N'
							]);
						}

						//Automatic messages
						(new AutomaticAction($session))->automaticAddMessage($messageId, $finishSession, $voteSession);

						$limit = ImConnectorConnector::getReplyLimit($params['connector']['connector_id']);
						$chat = $session->getChat();
						if (
							!empty($limit['BLOCK_DATE']) &&
							!empty($limit['BLOCK_REASON']) &&
							$chat
						)
						{
							$limit['BLOCK_DATE'] = (new DateTime())->add($limit['BLOCK_DATE'].' SECONDS');
							ReplyBlock::add($session->getData('ID'), $chat, $limit);
						}
						elseif (ImConnectorConnector::isNeedToAutoDeleteBlock($params['connector']['connector_id']))
						{
							ReplyBlock::delete($session->getData('ID'), $chat);
						}

						$updateSession = [
							'MESSAGE_COUNT' => true,
							'DATE_LAST_MESSAGE' => new DateTime(),
						];

						if (!$finishSession && !$voteSession)
						{
							//$updateSession['STATUS'] = Session::STATUS_CLIENT;
							$updateSession['INPUT_MESSAGE'] = true;
							$updateSession['DATE_MODIFY'] = new DateTime;
							$updateSession['USER_ID'] = $session->getData('USER_ID');
						}

						if (isset($params['extra']))
						{
							foreach($params['extra'] as $field => $value)
							{
								$oldValue = $session->getData($field);
								if ($oldValue != $value)
								{
									$updateSession[$field] = $value;
								}
							}
						}

						$session->update($updateSession);

						if (
							$session->getConfig('AGREEMENT_MESSAGE') == 'Y'
							&& !$session->chat->isNowCreated()
							&& $session->getUser()
							&& $session->getUser('USER_ID') == $params['message']['user_id']
							&& $session->getUser('USER_CODE')
							&& $session->getUser('AGREES') == 'N'
						)
						{
							ImOpenLinesCommon::setUserAgrees([
								'AGREEMENT_ID' => $session->getConfig('AGREEMENT_ID'),
								'CRM_ACTIVITY_ID' => $session->getData('CRM_ACTIVITY_ID'),
								'SESSION_ID' => $session->getData('SESSION_ID'),
								'CONFIG_ID' => $session->getData('CONFIG_ID'),
								'USER_CODE' => $session->getUser('USER_CODE'),
							]);
						}

						$queueManager = Queue::initialization($session);
						if ($queueManager)
						{
							$queueManager->automaticActionAddMessage($finishSession, $voteSession);
						}

						if (!$session->isNowCreated() && $finishSession === true)
						{
							$session->finish(true);
						}

						$this->callMessageTrigger($session, $messageId, $addMessage);

						//In case it's not a vote message or system message we make a new record
						if (!$voteSession && $params['message']['user_id'] != 0 && !User::getInstance($params['message']['user_id'])->isBot())
						{
							$kpi = new KpiManager($session->getData('ID'));
							$kpi->addMessage([
								'MESSAGE_ID' => $messageId,
								'LINE_ID' => $session->getData('CONFIG_ID'),
								'OPERATOR_ID' => $session->getData('OPERATOR_ID')
							]);
						}

						$result = [
							'SESSION_ID' => $session->isNowCreated()? $session->getData('ID'): 0,
							'MESSAGE_ID' => $messageId
						];
					}

					if (
						!$resultLoadSession
						&& $session->isCloseVote()
					)
					{
						Im::addCloseVoteMessage($session->getData('CHAT_ID'), $session->getConfig('VOTE_TIME_LIMIT'));
					}
				}

				$isAddMessage = true;
				ToolsLock::getInstance()->delete($keyLock);
			}
			else
			{
				sleep($iteration);
			}
		}
		while ($isAddMessage === false);
	}

	return $result;
}