• Модуль: im
  • Путь к файлу: ~/bitrix/modules/im/classes/general/im_messenger.php
  • Класс: CIMMessenger
  • Вызов: CIMMessenger::Add
static function Add($arFields)
{
	global $DB;

	$templateId = $arFields['TEMPLATE_ID'] ?? '';
	if (
		$arFields['MESSAGE_TYPE'] !== IM_MESSAGE_SYSTEM
		&& MessageUuid::validate($templateId)
	)
	{
		$messageUuid = new MessageUuid($templateId);
		$uuidAddResult = $messageUuid->add();
		// if it is false, then UUID already exists
		if (!$uuidAddResult)
		{
			$messageIdByUuid = $messageUuid->getMessageId();
			// if we got message_id, then message already exists, and we don't need to add it, so return with ID.
			if (!is_null($messageIdByUuid))
			{
				return $messageIdByUuid;
			}

			// if there is no message_id and entry date is expired,
			// then update date_create and return false to delay next sending on the client.
			if (!$messageUuid->updateIfExpired())
			{
				return false;
			}
		}
	}

	if (isset($arFields['DIALOG_ID']) && !empty($arFields['DIALOG_ID']))
	{
		if (BitrixImCommon::isChatId($arFields['DIALOG_ID']))
		{
			$arFields['TO_CHAT_ID'] = BitrixImDialog::getChatId($arFields['DIALOG_ID']);
			if (!isset($arFields['MESSAGE_TYPE']))
			{
				$arFields['MESSAGE_TYPE'] = IM_MESSAGE_CHAT;
			}
		}
		else
		{
			$arFields['TO_USER_ID'] = intval($arFields['DIALOG_ID']);
			$arFields['MESSAGE_TYPE'] = IM_MESSAGE_PRIVATE;
		}
	}

	if (isset($arFields['TITLE']) && !isset($arFields['NOTIFY_TITLE']))
		$arFields['NOTIFY_TITLE'] = mb_substr($arFields['TITLE'], 0, 255);

	if (isset($arFields['NOTIFY_MESSAGE']) && !isset($arFields['MESSAGE']))
		$arFields['MESSAGE'] = $arFields['NOTIFY_MESSAGE'];

	if (isset($arFields['NOTIFY_MESSAGE_OUT']) && !isset($arFields['MESSAGE_OUT']))
		$arFields['MESSAGE_OUT'] = $arFields['NOTIFY_MESSAGE_OUT'];

	if (isset($arFields['MESSAGE']))
	{
		$arFields['MESSAGE'] = trim(str_replace(Array('[BR]', '[br]', '#BR#'), "n", $arFields['MESSAGE']));
		if (mb_strlen($arFields['MESSAGE']) > self::MESSAGE_LIMIT + 6)
		{
			$arFields['MESSAGE'] = mb_substr($arFields['MESSAGE'], 0, self::MESSAGE_LIMIT).' (...)';
		}
	}

	if (
		isset($arFields['FROM_USER_ID'])
		&& (int)$arFields['FROM_USER_ID'] > 0
		&& BitrixImUser::getInstance($arFields['FROM_USER_ID'])->isExtranet())
	{
		$arFields['SYSTEM'] = 'N';
	}

	$isImportant = isset($arFields['IS_IMPORTANT']) && $arFields['IS_IMPORTANT'] === 'Y' ? 'Y' : 'N';

	$arFields['MESSAGE_OUT'] = isset($arFields['MESSAGE_OUT'])? trim($arFields['MESSAGE_OUT']): "";

	$arFields['URL_PREVIEW'] = isset($arFields['URL_PREVIEW']) && $arFields['URL_PREVIEW'] == 'N'? 'N': 'Y';
	$arFields['SKIP_URL_INDEX'] ??= 'N';

	$bConvert = false;
	if (isset($arFields['CONVERT']) && $arFields['CONVERT'] == 'Y')
		$bConvert = true;

	if (!isset($arFields['PARAMS']) || !is_array($arFields['PARAMS']))
	{
		$arFields['PARAMS'] = Array();
	}
	if (!isset($arFields['EXTRA_PARAMS']))
	{
		$arFields['EXTRA_PARAMS'] = Array();
	}

	$incrementCounter = true;
	/*
	if (isset($arFields['INCREMENT_COUNTER']) && $arFields['INCREMENT_COUNTER'] != 'Y')
	{
		if ($arFields['INCREMENT_COUNTER'] == 'N')
		{
			$incrementCounter = Array();
			$arFields['PARAMS']['NOTIFY'] = 'N';
		}
		else if (is_array($arFields['INCREMENT_COUNTER']))
		{
			$incrementCounter = array_values($arFields['INCREMENT_COUNTER']);
			$arFields['PARAMS']['NOTIFY'] = empty($incrementCounter)? 'N': $incrementCounter;
		}
	}
	*/

	if (!isset($arFields['MESSAGE_TYPE']))
		$arFields['MESSAGE_TYPE'] = "";

	if (!isset($arFields['NOTIFY_MODULE']))
		$arFields['NOTIFY_MODULE'] = 'im';

	if (!isset($arFields['NOTIFY_EVENT']))
		$arFields['NOTIFY_EVENT'] = 'default';

	if (isset($arFields['ATTACH']) || isset($arFields['PARAMS']['ATTACH']))
	{
		$attach = isset($arFields['ATTACH'])? $arFields['ATTACH']: $arFields['PARAMS']['ATTACH'];
		if (is_object($attach))
		{
			$arFields['PARAMS']['ATTACH'] = Array($attach);
		}
		else if (is_array($attach))
		{
			$arFields['PARAMS']['ATTACH'] = $attach;
		}
		else
		{
			$arFields['PARAMS']['ATTACH'] = Array();
		}
	}
	if (isset($arFields['FILES']))
	{
		if (is_array($arFields['FILES']))
		{
			$arFields['PARAMS']['FILE_ID'] = $arFields['FILES'];
		}
		else
		{
			$arFields['PARAMS']['FILE_ID'] = Array();
		}
	}
	if (isset($arFields['KEYBOARD']) || isset($arFields['PARAMS']['KEYBOARD']))
	{
		$keyboard = isset($arFields['KEYBOARD'])? $arFields['KEYBOARD']: $arFields['PARAMS']['KEYBOARD'];
		if (is_object($keyboard))
		{
			$arFields['PARAMS']['KEYBOARD'] = $keyboard;
		}
		else
		{
			$arFields['PARAMS']['KEYBOARD'] = Array();
		}
	}
	if (isset($arFields['MENU']) || isset($arFields['PARAMS']['MENU']))
	{
		$menu = isset($arFields['MENU'])? $arFields['MENU']: $arFields['PARAMS']['MENU'];
		if (is_object($menu))
		{
			$arFields['PARAMS']['MENU'] = $menu;
		}
		else
		{
			$arFields['PARAMS']['MENU'] = Array();
		}
	}

	if (isset($arFields['FOR_USER_ID'])) // TODO create this feature in future
	{
		$arFields['PARAMS']['FOR_USER_ID'] = $arFields['FOR_USER_ID'];
	}

	$arFields['RECENT_ADD'] = isset($arFields['RECENT_ADD']) && $arFields['RECENT_ADD'] == 'N'? 'N': 'Y';
	$arFields['SKIP_COMMAND'] = isset($arFields['SKIP_COMMAND']) && $arFields['SKIP_COMMAND'] == 'Y'? 'Y': 'N';
	$arFields['SKIP_CONNECTOR'] = isset($arFields['SKIP_CONNECTOR']) && $arFields['SKIP_CONNECTOR'] == 'Y'? 'Y': 'N';
	$arFields['IMPORTANT_CONNECTOR'] = isset($arFields['IMPORTANT_CONNECTOR']) && $arFields['IMPORTANT_CONNECTOR'] == 'Y'? 'Y': 'N';
	$arFields['SILENT_CONNECTOR'] = isset($arFields['SILENT_CONNECTOR']) && $arFields['SILENT_CONNECTOR'] == 'Y'? 'Y': 'N';
	if ($arFields['SILENT_CONNECTOR'] == 'Y')
	{
		$arFields['PARAMS']['CLASS'] = "bx-messenger-content-item-system";
	}

	$arFields['URL_ATTACH'] = Array();
	if ($arFields['MESSAGE_TYPE'] == IM_MESSAGE_SYSTEM)
	{
		if (!isset($arFields['NOTIFY_TYPE']) && intval($arFields['FROM_USER_ID']) > 0)
			$arFields['NOTIFY_TYPE'] = IM_NOTIFY_FROM;
		else if (!isset($arFields['NOTIFY_TYPE']))
			$arFields['NOTIFY_TYPE'] = IM_NOTIFY_SYSTEM;

		if (isset($arFields['NOTIFY_ANSWER']) && $arFields['NOTIFY_ANSWER'] == 'Y')
			$arFields['PARAMS']['CAN_ANSWER'] = 'Y';

		/*
		$urlPrepare = self::PrepareUrl($arFields['MESSAGE']);
		if ($urlPrepare['RESULT'])
		{
			if (empty($arFields['MESSAGE_OUT']))
			{
				$arFields['MESSAGE_OUT'] = $arFields['MESSAGE'];
			}
			$arFields['MESSAGE'] = $urlPrepare['MESSAGE'];
			$arFields['PARAMS']['ATTACH'] = array_merge($arFields['PARAMS']['ATTACH'], $urlPrepare['ATTACH']);
		}
		*/
	}
	else if ($arFields['URL_PREVIEW'] == 'Y')
	{
		$link = new CIMMessageLink();
		$message = $arFields['MESSAGE'] ?? null;
		$urlPrepare = $link->prepareInsert($message);
		if ($urlPrepare['RESULT'])
		{
			if (empty($arFields['MESSAGE_OUT']))
			{
				$arFields['MESSAGE_OUT'] = $arFields['MESSAGE'];
			}
			$arFields['MESSAGE'] = $urlPrepare['MESSAGE'];

			if (isset($arFields['PARAMS']['URL_ID']))
			{
				$arFields['PARAMS']['URL_ID'] = array_merge($arFields['PARAMS']['URL_ID'], $urlPrepare['URL_ID']);
			}
			else
			{
				$arFields['PARAMS']['URL_ID'] = $urlPrepare['URL_ID'];
			}
			$arFields['URL_ATTACH'] = $urlPrepare['ATTACH'];

			if ($urlPrepare['MESSAGE_IS_LINK'])
			{
				$arFields['PARAMS']['URL_ONLY'] = 'Y';
			}
		}
	}

	if (isset($arFields['NOTIFY_EMAIL_TEMPLATE']) && !isset($arFields['EMAIL_TEMPLATE']))
		$arFields['EMAIL_TEMPLATE'] = $arFields['NOTIFY_EMAIL_TEMPLATE'];

	if (!isset($arFields['AUTHOR_ID']))
	{
		$arFields['AUTHOR_ID'] = isset($arFields['FROM_USER_ID']) ? (int)$arFields['FROM_USER_ID'] : 0;
	}

	foreach(GetModuleEvents("im", "OnBeforeMessageNotifyAdd", true) as $arEvent)
	{
		$result = ExecuteModuleEventEx($arEvent, array(&$arFields));
		if($result===false || isset($result['result']) && $result['result'] === false)
		{
			$reason = self::GetReasonForMessageSendError($arFields['MESSAGE_TYPE'], $result['reason']);
			$GLOBALS["APPLICATION"]->ThrowException($reason, "ERROR_FROM_OTHER_MODULE");
			return false;
		}
	}
	if (!self::CheckFields($arFields))
	{
		return false;
	}

	if ($arFields['MESSAGE_TYPE'] != IM_MESSAGE_SYSTEM)
	{
		$message = $arFields['MESSAGE'] ?? null;
		if ($arFields['URL_PREVIEW'] === 'Y')
		{
			$results = BitrixImText::getDateConverterParams($message);
			foreach ($results as $result)
			{
				$arFields['PARAMS']['DATE_TEXT'][] = $result->getText();
				$arFields['PARAMS']['DATE_TS'][] = $result->getDate()->getTimestamp();
			}
		}

		if (BitrixImText::isOnlyEmoji($message))
		{
			$arFields['PARAMS']['LARGE_FONT'] = 'Y';
		}
	}


	if ($arFields['MESSAGE_TYPE'] == IM_MESSAGE_PRIVATE)
	{
		$isSelfChat = false;
		if (isset($arFields['TO_CHAT_ID']))
		{
			$chatId = $arFields['TO_CHAT_ID'];
			$relations = CIMChat::GetRelationById($chatId, false, true, false);

			$arFields['TO_USER_ID'] = $arFields['FROM_USER_ID'];
			foreach ($relations as $rel)
			{
				if (
					$arFields['TO_USER_ID']
					&& $rel['USER_ID'] == $arFields['FROM_USER_ID']
				)
				{
					continue;
				}

				$arFields['TO_USER_ID'] = $rel['USER_ID'];
			}
			if ($arFields['FROM_USER_ID'] == $arFields['TO_USER_ID'])
			{
				$isSelfChat = true;
			}
		}
		else
		{
			$arFields['FROM_USER_ID'] = intval($arFields['FROM_USER_ID']);
			$arFields['TO_USER_ID'] = intval($arFields['TO_USER_ID']);

			$chatId = CIMMessage::GetChatId($arFields['FROM_USER_ID'], $arFields['TO_USER_ID']);
			if ($arFields['FROM_USER_ID'] == $arFields['TO_USER_ID'])
			{
				$isSelfChat = true;
			}
		}

		if (!$bConvert && !BitrixImDialog::hasAccess($arFields['TO_USER_ID'], $arFields['FROM_USER_ID']))
		{
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CANCELED"), "ERROR_NO_ACCESS");
			return false;
		}

		if ($chatId > 0)
		{
			$chatData = BitrixImModelChatTable::getById($chatId)->fetch();
			$prevMessageId = intval($chatData['PREV_MESSAGE_ID']);

			$arFields['CHAT_ID'] = $chatId;
			$arFields = self::UploadFileFromText($arFields);
			if (!$arFields)
			{
				$GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_LINES_SHARE_FILE"), "LINES_SHARE");
				return false;
			}

			$arParams = Array();
			$arParams['CHAT_ID'] = $chatId;
			$arParams['AUTHOR_ID'] = intval($arFields['AUTHOR_ID']);
			$arParams['MESSAGE'] = $arFields['MESSAGE'] ?? null;
			$arParams['MESSAGE_OUT'] = $arFields['MESSAGE_OUT'];
			$arParams['NOTIFY_MODULE'] = $arFields['NOTIFY_MODULE'];
			$arParams['NOTIFY_EVENT'] = isset($arFields['SYSTEM']) && $arFields['SYSTEM'] === 'Y' ? 'private_system': 'private';

			if (isset($arFields['IMPORT_ID']))
				$arParams['IMPORT_ID'] = intval($arFields['IMPORT_ID']);

			if (isset($arFields['MESSAGE_DATE']))
			{
				$arParams['DATE_CREATE'] = new BitrixMainTypeDateTime($arFields['MESSAGE_DATE']);
			}
			$arFiles = Array();
			$arFields['FILES'] = Array();
			if (isset($arFields['PARAMS']['FILE_ID']))
			{
				foreach ($arFields['PARAMS']['FILE_ID'] as $fileId)
				{
					$arFiles[$fileId] = $fileId;
				}
			}
			$arFields['FILES'] = CIMDisk::GetFiles($chatId, $arFiles, false);

			$messageFiles = self::GetFormatFilesMessageOut($arFields['FILES']);
			if ($messageFiles <> '')
			{
				$arParams['MESSAGE_OUT'] = $arParams['MESSAGE_OUT'] <> ''? $arParams['MESSAGE_OUT']."n".$messageFiles: $messageFiles;
				$arFields['MESSAGE_OUT'] = $arParams['MESSAGE_OUT'];
			}

			$result = BitrixImModelMessageTable::add($arParams);
			$messageID = intval($result->getId());
			if ($messageID <= 0)
				return false;

			if (isset($messageUuid))
			{
				$messageUuid->updateMessageId($messageID);
			}

			BitrixImModelChatTable::update($chatId, Array(
				'MESSAGE_COUNT' => new BitrixMainDBSqlExpression('?# + 1', 'MESSAGE_COUNT'),
				//'PREV_MESSAGE_ID' => new BitrixMainDBSqlExpression('?#', 'LAST_MESSAGE_ID'),
				'LAST_MESSAGE_ID' => $messageID,
				//'LAST_MESSAGE_STATUS' => IM_MESSAGE_STATUS_RECEIVED
			));

			if ($chatData['PARENT_MID'])
			{
				CIMMessageParam::set($chatData['PARENT_MID'], Array(
					'CHAT_MESSAGE' => $chatData['MESSAGE_COUNT']+1,
					'CHAT_LAST_DATE' => new BitrixMainTypeDateTime()
				));
				CIMMessageParam::SendPull($chatData['PARENT_MID'], Array('CHAT_MESSAGE', 'CHAT_LAST_DATE'));
			}

			if (empty($arFields['PARAMS']))
			{
				CIMMessageParam::UpdateTimestamp($messageID, $arParams['CHAT_ID']);
			}
			else
			{
				CIMMessageParam::Set($messageID, $arFields['PARAMS']);
			}

			if (!empty($arFields['URL_ATTACH']))
			{
				if (isset($arFields['PARAMS']['ATTACH']))
				{
					$arFields['PARAMS']['ATTACH'] = array_merge($arFields['PARAMS']['ATTACH'], $arFields['URL_ATTACH']);
				}
				else
				{
					$arFields['PARAMS']['ATTACH'] = $arFields['URL_ATTACH'];
				}
			}

			$relations = CIMChat::GetRelationById($chatId, false, true, false);
			$message = new BitrixImV2Message($arParams);
			$message->setParams($arFields['PARAMS'] ?? []);
			$message->setMessageId($messageID);
			foreach ($relations as $relation)
			{
				if (BitrixImUser::getInstance($relation['USER_ID'])->isBot())
				{
					// bot
				}
				else if (!BitrixImUser::getInstance($relation['USER_ID'])->isActive())
				{
					continue;
				}

				if (isset($arFields['RECENT_SKIP_AUTHOR']) && $relation['USER_ID'] == $arParams['AUTHOR_ID'])
				{
					continue;
				}

				$addToRecent = true;
				if ($incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter))
				{
					$addToRecent = CIMContactList::InRecent($relation['USER_ID'], $arFields['MESSAGE_TYPE'], $relation['CHAT_ID']);
				}
				if ($addToRecent)
				{
					CIMContactList::SetRecent(Array(
						'ENTITY_ID' => $relation['USER_ID'] == $arFields['TO_USER_ID']? $arFields['FROM_USER_ID']: $arFields['TO_USER_ID'],
						'MESSAGE_ID' => $messageID,
						'CHAT_TYPE' => IM_MESSAGE_PRIVATE,
						'CHAT_ID' => $relation['CHAT_ID'],
						'RELATION_ID' => $relation['ID'],
						'USER_ID' => $relation['USER_ID']
					));
				}
			}

			if (!$bConvert)
			{
				$pullIncluded = CModule::IncludeModule("pull");
				$pullServerActive = $pullIncluded && CPullOptions::GetNginxStatus();
				$relations = BitrixImChat::getRelation($chatId, Array(
					//'REAL_COUNTERS' => 'Y',
					'WITHOUT_COUNTERS' => 'Y',
					'USER_DATA' => 'Y',
				));
				$relationCollection = new BitrixImV2RelationCollection();
				foreach ($relations as $id => $relation)
				{
					if (BitrixImUser::getInstance($relation["USER_ID"])->isBot())
					{
						// bot
					}
					else if ($relation['USER_DATA']['ACTIVE'] == 'N')
					{
						continue;
					}

					$relationObject = new BitrixImV2Relation([
						'USER_ID' => (int)$relation['USER_ID'],
						'CHAT_ID' => $relation['CHAT_ID'],
						'MESSAGE_TYPE' => $relation['MESSAGE_TYPE'],
						'NOTIFY_BLOCK' => $relation['NOTIFY_BLOCK'] === 'Y',
					]);
					$relationObject->setId((int)$relation['ID']);
					$relationCollection->add($relationObject);
					if ($isSelfChat || $relation["USER_ID"] == $arFields["FROM_USER_ID"])
					{
						$relations[$id]['COUNTER'] = 0;
						$relationUpdate = array(
							//"STATUS" => IM_STATUS_READ,
							//"MESSAGE_STATUS" => IM_MESSAGE_STATUS_RECEIVED,
							//"UNREAD_ID" => $messageID,
							//"COUNTER" => 0,
							"LAST_ID" => $messageID,
							//"LAST_SEND_ID" => $messageID,
							//"LAST_READ" => new BitrixMainTypeDateTime(),
						);
						/*if (!$pullServerActive)
						{
							unset($relationUpdate['STATUS']);
							unset($relationUpdate['LAST_ID']);
						}*/
						if ($pullServerActive)
						{
							BitrixImModelRelationTable::update($relation["ID"], $relationUpdate);
						}
					}
					else
					{
						/*$updateRelation = array(
							"STATUS" => IM_STATUS_UNREAD,
							"MESSAGE_STATUS" => IM_MESSAGE_STATUS_RECEIVED,
							"UNREAD_ID" => $messageID,
							"COUNTER" => $relation['COUNTER'],
						);
						if ($relation["UNREAD_ID"])
						{
							unset($updateRelation['UNREAD_ID']);
						}
						if ($incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter))
						{
							unset($updateRelation['COUNTER']);
						}

						BitrixImModelRelationTable::update($relation["ID"], $updateRelation);*/
					}

					//BitrixImCounter::clearCache($relation['USER_ID']);
				}
				$counters = (new BitrixImV2MessageReadService((int)$arFields["FROM_USER_ID"]))
					->onAfterMessageSend($message, $relationCollection)
					->getResult()['COUNTERS']
				;

				$importantFor = self::getMentionUsers($arParams['MESSAGE'] ?? '');

				if (CModule::IncludeModule("pull"))
				{
					$arParams['FROM_USER_ID'] = $arFields['FROM_USER_ID'];
					$arParams['TO_USER_ID'] = $arFields['TO_USER_ID'];

					$pullMessage = Array(
						'module_id' => 'im',
						'command' => 'message',
						'params' => CIMMessage::GetFormatMessage(Array(
							'ID' => $messageID,
							'TEMPLATE_ID' => $arFields['TEMPLATE_ID'] ?? null,
							'FILE_TEMPLATE_ID' => $arFields['FILE_TEMPLATE_ID'] ?? null,
							'PREV_ID' => $prevMessageId,
							'CHAT_ID' => $chatId,
							'TO_USER_ID' => $arParams['TO_USER_ID'],
							'FROM_USER_ID' => $arParams['FROM_USER_ID'],
							'SYSTEM' => isset($arFields['SYSTEM']) && $arFields['SYSTEM'] === 'Y' ? 'Y' : 'N',
							'MESSAGE' => $arParams['MESSAGE'],
							'DATE_CREATE' => time(),
							'PARAMS' => self::PrepareParamsForPull($arFields['PARAMS']),
							'FILES' => $arFields['FILES'],
							'NOTIFY' => $incrementCounter,
							'IMPORTANT_FOR' => $importantFor,
							'IS_IMPORTANT' => $isImportant,
						)),
						'extra' => BitrixImCommon::getPullExtra()
					);

					$pullMessageTo = $pullMessage;
					$pullMessageTo['params']['dialogId'] = $arParams['FROM_USER_ID'];

					$pullMessageFrom = $pullMessage;
					$pullMessageFrom['params']['dialogId'] = $arParams['TO_USER_ID'];

					$pullMessageFrom['params']['counter'] = $counters[(int)$arParams['FROM_USER_ID']] ?? 0;
					BitrixPullEvent::add($arParams['FROM_USER_ID'], $pullMessageFrom);

					if ($arParams['FROM_USER_ID'] != $arParams['TO_USER_ID'])
					{
						$pullMessageTo['params']['counter'] = $counters[(int)$arParams['TO_USER_ID']] ?? 0;
						BitrixPullEvent::add($arParams['TO_USER_ID'], $pullMessageTo);

						$pullMessageTo = self::PreparePushForPrivate($pullMessageTo);
						$pullMessageFrom = self::PreparePushForPrivate($pullMessageFrom);

						if (
							!isset($arFields['PUSH'])
							|| isset($arFields['PUSH']) && $arFields['PUSH'] === 'Y'
						)
						{
							if (isset($arFields['MESSAGE_PUSH']))
							{
								$pullMessageTo['push']['message'] = $arFields['MESSAGE_PUSH'];
								$pullMessageTo['push']['advanced_params']['senderMessage'] = $arFields['MESSAGE_PUSH'];
								$pullMessageFrom['push']['message'] = $arFields['MESSAGE_PUSH'];
								$pullMessageFrom['push']['advanced_params']['senderMessage'] = $arFields['MESSAGE_PUSH'];
							}

							$pullMessageTo['push']['advanced_params']['counter'] = $counters[$arParams['TO_USER_ID']] ?? 0;
							BitrixPullPush::add($arParams['TO_USER_ID'], $pullMessageTo);

							$pullMessageFrom['push']['advanced_params']['counter'] = $counters[$arParams['FROM_USER_ID']] ?? 0;
							BitrixPullPush::add($arParams['FROM_USER_ID'], array_merge_recursive($pullMessageFrom, ['push' => [
								'skip_users' => [$arParams['FROM_USER_ID']],
								'advanced_params' => [
									"notificationsToCancel" => ['IM_MESS'],
								],
								'send_immediately' => 'Y',
							]]));
						}
					}
				}

				foreach(GetModuleEvents("im", "OnAfterMessagesAdd", true) as $arEvent)
					ExecuteModuleEventEx($arEvent, array(intval($messageID), $arFields));

				$arFields['COMMAND_CONTEXT'] = 'TEXTAREA';
				$result = BitrixImCommand::onCommandAdd(intval($messageID), $arFields);
				if (!$result)
				{
					BitrixImBot::onMessageAdd(intval($messageID), $arFields);
				}

				if ($arFields['SKIP_URL_INDEX'] !== 'Y')
				{
					(new BitrixImV2LinkUrlUrlService())->saveUrlsFromMessage($message);
				}

				(new BitrixImV2LinkFileFileService())->saveFilesFromMessage($arFields['FILES_FROM_TEXT'] ?? [], $message);
			}

			BitrixImModelMessageTable::indexRecord($messageID);

			return $messageID;
		}
		else
		{
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID");
			return false;
		}
	}
	else if ($arFields['MESSAGE_TYPE'] == IM_MESSAGE_CHAT || $arFields['MESSAGE_TYPE'] == IM_MESSAGE_OPEN || $arFields['MESSAGE_TYPE'] == IM_MESSAGE_OPEN_LINE)
	{
		$arFields['SKIP_USER_CHECK'] = isset($arFields['SKIP_USER_CHECK']) && $arFields['SKIP_USER_CHECK'] == 'Y'? 'Y': 'N';
		$arFields['FROM_USER_ID'] = isset($arFields['FROM_USER_ID']) ? (int)$arFields['FROM_USER_ID'] : 0;
		$chatId = 0;
		$systemMessage = false;
		if (isset($arFields['SYSTEM']) && $arFields['SYSTEM'] == 'Y')
		{
			$strSql = "
				SELECT
					C.ID CHAT_ID,
					C.PARENT_ID CHAT_PARENT_ID,
					C.PARENT_MID CHAT_PARENT_MID,
					C.TITLE CHAT_TITLE,
					C.AUTHOR_ID CHAT_AUTHOR_ID,
					C.TYPE CHAT_TYPE,
					C.AVATAR CHAT_AVATAR,
					C.COLOR CHAT_COLOR,
					C.ENTITY_TYPE CHAT_ENTITY_TYPE,
					C.ENTITY_ID CHAT_ENTITY_ID,
					C.ENTITY_DATA_1 CHAT_ENTITY_DATA_1,
					C.ENTITY_DATA_2 CHAT_ENTITY_DATA_2,
					C.ENTITY_DATA_3 CHAT_ENTITY_DATA_3,
					C.EXTRANET CHAT_EXTRANET,
					C.PREV_MESSAGE_ID CHAT_PREV_MESSAGE_ID,
					C.CAN_POST CHAT_CAN_POST,
					'1' RID,
					'Y' IS_MANAGER
				FROM b_im_chat C
				WHERE C.ID = ".intval($arFields['TO_CHAT_ID'])."
			";
			$systemMessage = true;
		}
		else
		{
			$strSql = "
				SELECT
					C.ID CHAT_ID,
					C.PARENT_ID CHAT_PARENT_ID,
					C.PARENT_MID CHAT_PARENT_MID,
					C.TITLE CHAT_TITLE,
					C.AUTHOR_ID CHAT_AUTHOR_ID,
					C.TYPE CHAT_TYPE,
					C.AVATAR CHAT_AVATAR,
					C.COLOR CHAT_COLOR,
					C.ENTITY_TYPE CHAT_ENTITY_TYPE,
					C.ENTITY_ID CHAT_ENTITY_ID,
					C.ENTITY_DATA_1 CHAT_ENTITY_DATA_1,
					C.ENTITY_DATA_2 CHAT_ENTITY_DATA_2,
					C.ENTITY_DATA_3 CHAT_ENTITY_DATA_3,
					C.EXTRANET CHAT_EXTRANET,
					C.PREV_MESSAGE_ID CHAT_PREV_MESSAGE_ID,
					C.CAN_POST CHAT_CAN_POST,
					R.USER_ID RID,
					R.MANAGER IS_MANAGER
				FROM b_im_chat C
				LEFT JOIN b_im_relation R ON R.CHAT_ID = C.ID AND R.USER_ID = ".$arFields['FROM_USER_ID']."
				WHERE C.ID = ".intval($arFields['TO_CHAT_ID'])."
			";
		}

		$dbRes = $DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__); if ($arRes = $dbRes->Fetch()) { $chatId = intval($arRes['CHAT_ID']); $chatTitle = htmlspecialcharsbx(BitrixImText::decodeEmoji($arRes['CHAT_TITLE'])); $chatAuthorId = intval($arRes['CHAT_AUTHOR_ID']); $chatParentId = intval($arRes['CHAT_PARENT_ID']); $chatParentMid = intval($arRes['CHAT_PARENT_MID']); $chatExtranet = $arRes['CHAT_EXTRANET'] == 'Y'; $arRes['CHAT_TYPE'] = trim($arRes['CHAT_TYPE']); $arFields['MESSAGE_TYPE'] = $arRes['CHAT_TYPE']; $prevMessageId = intval($arRes['CHAT_PREV_MESSAGE_ID']); $importantPush = $arRes['CHAT_ENTITY_TYPE'] == 'ANNOUNCEMENT'; if ($arFields['SKIP_USER_CHECK'] == 'N') { if ((int)$arFields['FROM_USER_ID'] !== 0) { $userRole = BitrixImV2Chat::ROLE_MEMBER; if ($arRes['IS_MANAGER'] === 'Y') { $userRole = BitrixImV2Chat::ROLE_MANAGER; } if ((int)$arRes['CHAT_AUTHOR_ID'] === (int)$arFields['FROM_USER_ID']) { $userRole = BitrixImV2Chat::ROLE_OWNER; } if (!BitrixImV2ChatPermission::compareRole($userRole, $arRes['CHAT_CAN_POST'] ?? '')) { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED"); return false; } } if ($arRes['CHAT_ENTITY_TYPE'] == 'ANNOUNCEMENT' && $arRes['IS_MANAGER'] !== 'Y') { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED"); return false; } if ($arRes['CHAT_TYPE'] == IM_MESSAGE_OPEN) { if (!CIMMessenger::CheckEnableOpenChat()) { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED"); return false; } else if (intval($arRes['RID']) <= 0) { if (BitrixImUser::getInstance($arFields['FROM_USER_ID'])->isExtranet()) { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED"); return false; } else { $chat = new CIMChat(0); $chat->AddUser($chatId, $arFields['FROM_USER_ID']); } } } else if (intval($arRes['RID']) <= 0) { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED"); return false; } } } else { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED"); return false; } if ($chatId > 0) { foreach(GetModuleEvents("im", "OnBeforeChatMessageAdd", true) as $arEvent) { $result = ExecuteModuleEventEx($arEvent, array($arFields, $arRes)); if($result===false || isset($result['result']) && $result['result'] === false) { $reason = self::GetReasonForMessageSendError($arFields['MESSAGE_TYPE'], $result['reason']); $GLOBALS["APPLICATION"]->ThrowException($reason, "ERROR_FROM_OTHER_MODULE"); return false; } if (isset($result['fields'])) { $arFields = $result['fields']; } } $chatId = intval($arRes['CHAT_ID']); $arFields['CHAT_ID'] = $chatId; $arFields = self::UploadFileFromText($arFields); $arParams = Array(); $arParams['CHAT_ID'] = $chatId; $arParams['AUTHOR_ID'] = $systemMessage? 0: intval($arFields['AUTHOR_ID']); $arParams['MESSAGE'] = $arFields['MESSAGE'] ?? null; $arParams['MESSAGE_OUT'] = $arFields['MESSAGE_OUT']; $arParams['NOTIFY_MODULE'] = 'im'; $arParams['NOTIFY_EVENT'] = 'group'; if (isset($arFields['MESSAGE_DATE'])) { $arParams['DATE_CREATE'] = new BitrixMainTypeDateTime($arFields['MESSAGE_DATE']); } $arFiles = Array(); $arFields['FILES'] = Array(); if (isset($arFields['PARAMS']['FILE_ID'])) { foreach ($arFields['PARAMS']['FILE_ID'] as $fileId) { $arFiles[$fileId] = $fileId; } } $arFields['FILES'] = CIMDisk::GetFiles($chatId, $arFiles, false); $messageFiles = self::GetFormatFilesMessageOut($arFields['FILES']); if ($messageFiles <> '') { $arParams['MESSAGE_OUT'] = $arParams['MESSAGE_OUT'] <> ''? $arParams['MESSAGE_OUT']."n".$messageFiles: $messageFiles; $arFields['MESSAGE_OUT'] = $arParams['MESSAGE_OUT']; } $result = BitrixImModelMessageTable::add($arParams); $messageID = intval($result->getId()); if ($messageID <= 0) return false; if (isset($messageUuid)) { $messageUuid->updateMessageId($messageID); } if (empty($arFields['PARAMS'])) { CIMMessageParam::UpdateTimestamp($messageID, $arParams['CHAT_ID']); } else { CIMMessageParam::Set($messageID, $arFields['PARAMS']); } if (!empty($arFields['URL_ATTACH'])) { if (isset($arFields['PARAMS']['ATTACH'])) { $arFields['PARAMS']['ATTACH'] = array_merge($arFields['PARAMS']['ATTACH'], $arFields['URL_ATTACH']); } else { $arFields['PARAMS']['ATTACH'] = $arFields['URL_ATTACH']; } } if (!$bConvert) { BitrixImModelChatTable::update($chatId, Array( 'MESSAGE_COUNT' => new BitrixMainDBSqlExpression('?# + 1', 'MESSAGE_COUNT'), //'PREV_MESSAGE_ID' => new BitrixMainDBSqlExpression('?#', 'LAST_MESSAGE_ID'), 'LAST_MESSAGE_ID' => $messageID, //'LAST_MESSAGE_STATUS' => IM_MESSAGE_STATUS_RECEIVED )); if ($chatParentMid) { $chatData = BitrixImModelChatTable::getById($chatId)->fetch(); CIMMessageParam::set($chatParentMid, Array( 'CHAT_MESSAGE' => $chatData['MESSAGE_COUNT'], 'CHAT_LAST_DATE' => new BitrixMainTypeDateTime() )); CIMMessageParam::SendPull($chatParentMid, Array('CHAT_MESSAGE', 'CHAT_LAST_DATE')); } $arParams['FROM_USER_ID'] = $arFields['FROM_USER_ID']; $arParams['TO_CHAT_ID'] = $arFields['TO_CHAT_ID']; $arBotInChat = Array(); $relations = BitrixImChat::getRelation($chatId, Array( //'REAL_COUNTERS' => 'Y', 'WITHOUT_COUNTERS' => 'Y', 'USER_DATA' => 'Y', 'SKIP_CONNECTOR' => $arRes['CHAT_ENTITY_TYPE'] == 'LINES'? 'Y': 'N' )); $pullIncluded = CModule::IncludeModule("pull"); $pullServerActive = $pullIncluded && CPullOptions::GetNginxStatus(); $events = []; $skippedRelations = []; $pushUserSkip = []; $pushUserSend = []; $relationCollection = new BitrixImV2RelationCollection(); foreach ($relations as $id => $relation) { if ($arFields['RECENT_ADD'] != 'Y') { $skippedRelations[$id] = true; continue; } if ($relation['USER_DATA']["EXTERNAL_AUTH_ID"] == BitrixImBot::EXTERNAL_AUTH_ID) { $arBotInChat[$relation["USER_ID"]] = $relation["USER_ID"]; } else if ($relation['USER_DATA']['ACTIVE'] == 'N') { $skippedRelations[$id] = true; continue; } $sessionId = 0; if ($arRes['CHAT_ENTITY_TYPE'] == "LINES") { if ($relation['USER_DATA']["EXTERNAL_AUTH_ID"] == 'imconnector') { $skippedRelations[$id] = true; continue; } if ($arRes['CHAT_ENTITY_DATA_1']) { $fieldData = explode("|", $arRes['CHAT_ENTITY_DATA_1']); $sessionId = intval($fieldData[5]); } } $addToRecent = true; if ($incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter)) { $addToRecent = CIMContactList::InRecent($relation['USER_ID'], $arFields['MESSAGE_TYPE'], $relation['CHAT_ID']); } if ($addToRecent) { CIMContactList::SetRecent([ 'ENTITY_ID' => $chatId, 'MESSAGE_ID' => $messageID, 'CHAT_TYPE' => $arFields['MESSAGE_TYPE'], 'USER_ID' => $relation['USER_ID'], 'CHAT_ID' => $relation['CHAT_ID'], 'RELATION_ID' => $relation['ID'], 'SESSION_ID' => $sessionId, ]); } $relationObject = new BitrixImV2Relation([ 'USER_ID' => (int)$relation['USER_ID'], 'CHAT_ID' => $relation['CHAT_ID'], 'MESSAGE_TYPE' => $relation['MESSAGE_TYPE'], 'NOTIFY_BLOCK' => $relation['NOTIFY_BLOCK'] === 'Y', ]); $relationObject->setId((int)$relation['ID']); $relationCollection->add($relationObject); if ($relation["USER_ID"] == $arFields["FROM_USER_ID"]) { $relations[$id]['COUNTER'] = $relation['COUNTER'] = 0; $relationUpdate = array( //"STATUS" => IM_STATUS_READ, //"MESSAGE_STATUS" => IM_MESSAGE_STATUS_RECEIVED, //"COUNTER" => 0, //"UNREAD_ID" => $messageID, "LAST_ID" => $messageID, //"LAST_SEND_ID" => $messageID, //"LAST_READ" => new BitrixMainTypeDateTime(), ); /*if (!$pullServerActive) { unset($relationUpdate['STATUS']); unset($relationUpdate['LAST_ID']); }*/ if ($pullServerActive) { BitrixImModelRelationTable::update($relation["ID"], $relationUpdate); } } else { /*$updateRelation = array( "STATUS" => IM_STATUS_UNREAD, "UNREAD_ID" => $messageID, "MESSAGE_STATUS" => IM_MESSAGE_STATUS_RECEIVED, "COUNTER" => $relation['COUNTER'], ); if ($relation["UNREAD_ID"]) { unset($updateRelation['UNREAD_ID']); } if ($incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter)) { unset($updateRelation['COUNTER']); } BitrixImModelRelationTable::update($relation["ID"], $updateRelation);*/ } //BitrixImCounter::clearCache($relation['USER_ID']); if (!$pullIncluded) { continue; } $sendPush = true; if ($relation['USER_ID'] == $arParams['FROM_USER_ID']) { CPushManager::DeleteFromQueueBySubTag($arParams['FROM_USER_ID'], 'IM_MESS'); $sendPush = false; } else if ($relation['NOTIFY_BLOCK'] == 'Y' && !$importantPush) { $pushUserSkip[] = $relation['USER_ID']; $pushUserSend[] = $relation['USER_ID']; } else if (isset($arFields['PUSH']) && $arFields['PUSH'] === 'N') { $sendPush = false; } else { $pushUserSend[] = $relation['USER_ID']; } } $message = new BitrixImV2Message($arParams); $message->setParams($arFields['PARAMS'] ?? []); $message->setMessageId($messageID); $counters = (new BitrixImV2MessageReadService((int)$arFields["FROM_USER_ID"])) ->onAfterMessageSend($message, $relationCollection) ->getResult()['COUNTERS'] ; $importantFor = self::getMentionUsers($arParams['MESSAGE'] ?? ''); $pullMessage = [ 'module_id' => 'im', 'command' => 'messageChat', 'params' => CIMMessage::GetFormatMessage([ 'ID' => $messageID, 'TEMPLATE_ID' => $arFields['TEMPLATE_ID'] ?? null, 'FILE_TEMPLATE_ID' => $arFields['FILE_TEMPLATE_ID'] ?? null, 'PREV_ID' => $prevMessageId, 'CHAT_ID' => $chatId, 'TO_CHAT_ID' => $arParams['TO_CHAT_ID'], 'FROM_USER_ID' => $arParams['FROM_USER_ID'], 'MESSAGE' => $arParams['MESSAGE'], 'SYSTEM' => ($arFields['SYSTEM'] ?? null) === 'Y' ? 'Y' : 'N', 'DATE_CREATE' => time(), 'PARAMS' => self::PrepareParamsForPull($arFields['PARAMS']), 'FILES' => $arFields['FILES'], 'EXTRA_PARAMS' => $arFields['EXTRA_PARAMS'], 'COUNTER' => -1, 'NOTIFY' => $incrementCounter, 'IMPORTANT_FOR' => $importantFor, 'IS_IMPORTANT' => $isImportant, ]), 'extra' => BitrixImCommon::getPullExtra() ]; foreach ($relations as $id => $relation) { $skippedRelation = $skippedRelations[$id] ?? null; if ($skippedRelation) { continue; } $events[$relation['USER_ID']] = $pullMessage; $events[$relation['USER_ID']]['params']['counter'] = $counters[$relation['USER_ID']] ?? 0; //$events[$relation['USER_ID']]['params']['counter'] = $incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter)? $relation['PREVIOUS_COUNTER']: $relation['COUNTER']; $events[$relation['USER_ID']]['groupId'] = 'im_chat_'.$chatId.'_'.$messageID.'_'.$events[$relation['USER_ID']]['params']['counter']; } if (($arFields['SYSTEM'] ?? null) !== 'Y') { self::SendMention([ 'CHAT_ID' => $chatId, 'CHAT_TITLE' => $chatTitle, 'CHAT_RELATION' => $relations, 'CHAT_TYPE' => $arFields['MESSAGE_TYPE'], 'CHAT_ENTITY_TYPE' => $arRes['CHAT_ENTITY_TYPE'], 'CHAT_COLOR' => $arRes['CHAT_COLOR'], 'MESSAGE' => $arParams['MESSAGE'], 'FILES' => $arFields['FILES'], 'FROM_USER_ID' => $arParams['FROM_USER_ID'], 'MENTION_USERS' => $importantFor, ]); } if ($pullIncluded) { if ($arRes['CHAT_TYPE'] == IM_MESSAGE_OPEN || $arRes['CHAT_TYPE'] == IM_MESSAGE_OPEN_LINE) { $watchPullMessage = $pullMessage; $watchPullMessage['params']['message']['params']['NOTIFY'] = 'N'; CPullWatch::AddToStack('IM_PUBLIC_' . $chatId, $watchPullMessage); } $groups = self::GetEventByCounterGroup($events); foreach ($groups as $group) { BitrixPullEvent::add($group['users'], $group['event']); $userList = array_intersect($pushUserSend, $group['users']); if (!empty($userList)) { $pushParams = $group['event']; $pushParams = self::PreparePushForChat($pushParams); if ($importantPush) { $pushParams['push']['important'] = 'Y'; } $pushParams['skip_users'] = $pushUserSkip; if (isset($arFields['MESSAGE_PUSH'])) { $pushParams['push']['message'] = $arFields['MESSAGE_PUSH']; $pushParams['push']['advanced_params']['senderMessage'] = $arFields['MESSAGE_PUSH']; } $pushParams['push']['advanced_params']['counter'] = $group['event']['params']['counter']; BitrixPullPush::add($userList, $pushParams); } } } $arFields['CHAT_AUTHOR_ID'] = $chatAuthorId; $arFields['CHAT_ENTITY_TYPE'] = $arRes['CHAT_ENTITY_TYPE']; $arFields['CHAT_ENTITY_ID'] = $arRes['CHAT_ENTITY_ID']; $arFields['CHAT_ENTITY_DATA_1'] = $arRes['CHAT_ENTITY_DATA_1']; $arFields['CHAT_ENTITY_DATA_2'] = $arRes['CHAT_ENTITY_DATA_2']; $arFields['CHAT_ENTITY_DATA_3'] = $arRes['CHAT_ENTITY_DATA_3']; $arFields['BOT_IN_CHAT'] = $arBotInChat; foreach (GetModuleEvents("im", "OnAfterMessagesAdd", true) as $arEvent) ExecuteModuleEventEx($arEvent, [intval($messageID), $arFields]); $arFields['COMMAND_CONTEXT'] = 'TEXTAREA'; $result = BitrixImCommand::onCommandAdd(intval($messageID), $arFields); if (!$result) { BitrixImBot::onMessageAdd(intval($messageID), $arFields); } if ($arFields['SKIP_URL_INDEX'] !== 'Y') { (new BitrixImV2LinkUrlUrlService())->saveUrlsFromMessage($message); } (new BitrixImV2LinkFileFileService())->saveFilesFromMessage($arFields['FILES_FROM_TEXT'] ?? [], $message); } BitrixImModelMessageTable::indexRecord($messageID); return $messageID; } else { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID"); return false; } } else if ($arFields['MESSAGE_TYPE'] == IM_MESSAGE_SYSTEM) { $arFields['TO_USER_ID'] = intval($arFields['TO_USER_ID']); $blockedExternalAuthId = BitrixImModelUserTable::filterExternalUserTypes(['replica']); $orm = BitrixImModelUserTable::getById($arFields['TO_USER_ID']); $userData = $orm->fetch(); if ( !$userData || $userData['ACTIVE'] == 'N' || in_array($userData['EXTERNAL_AUTH_ID'], $blockedExternalAuthId, true) ) { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "TO_USER_ID"); return false; } $strSql = " SELECT ID CHAT_ID FROM b_im_chat WHERE AUTHOR_ID = ".$arFields['TO_USER_ID']." AND TYPE = '".IM_MESSAGE_SYSTEM."' ORDER BY ID ASC "; $dbRes = $DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__); if ($arRes = $dbRes->Fetch()) { $chatId = intval($arRes['CHAT_ID']); } else { $result = BitrixImV2ChatChatFactory::getInstance()->addChat([ 'TYPE' => IM_MESSAGE_SYSTEM, 'AUTHOR_ID' => $arFields['TO_USER_ID'] ]); if (!$result->isSuccess() || !$result->hasResult()) { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID"); return false; } $chatId = $result->getResult()['CHAT_ID']; if ($chatId <= 0) { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID"); return false; } /*BitrixImModelRelationTable::add(array( "CHAT_ID" => $chatId, "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM, "USER_ID" => intval($arFields['TO_USER_ID']), //"STATUS" => ($bConvert? 2: 0), ));*/ } if ($chatId > 0) { $arFields['MESSAGE'] = BitrixImText::convertHtmlToBbCode($arFields['MESSAGE']); if (isset($arFields['PUSH_MESSAGE'])) { $arFields['PUSH_MESSAGE'] = $html = str_replace(' ', ' ', $arFields['PUSH_MESSAGE']);; } $arParams = Array(); $arParams['CHAT_ID'] = $chatId; $arParams['AUTHOR_ID'] = intval($arFields['AUTHOR_ID']); $arParams['MESSAGE'] = $arFields['MESSAGE']; $arParams['MESSAGE_OUT'] = $arFields['MESSAGE_OUT']; $arParams['NOTIFY_TYPE'] = intval($arFields['NOTIFY_TYPE']); $arParams['NOTIFY_MODULE'] = $arFields['NOTIFY_MODULE']; $arParams['NOTIFY_EVENT'] = $arFields['NOTIFY_EVENT']; //if (mb_strlen($arParams['MESSAGE']) <= 0 && mb_strlen($arParams['MESSAGE_OUT']) <= 0) // return false; $skipAdd = false; $skipFlash = false; if ($arParams['NOTIFY_TYPE'] != IM_NOTIFY_CONFIRM) { $skipAdd = !CIMSettings::GetNotifyAccess($arFields["TO_USER_ID"], $arFields["NOTIFY_MODULE"], $arFields["NOTIFY_EVENT"], CIMSettings::CLIENT_SITE); $skipFlash = $skipAdd; } if (!$skipAdd && ($arFields['NOTIFY_ONLY_FLASH'] ?? null) === 'Y') { $skipAdd = true; } if ($skipAdd) { $arParams['NOTIFY_READ'] = 'Y'; } if (isset($arFields['IMPORT_ID'])) $arParams['IMPORT_ID'] = intval($arFields['IMPORT_ID']); if (isset($arFields['MESSAGE_DATE'])) { $arParams['DATE_CREATE'] = new BitrixMainTypeDateTime($arFields['MESSAGE_DATE']); } if (isset($arFields['EMAIL_TEMPLATE']) && trim($arFields['EMAIL_TEMPLATE']) <> '') $arParams['EMAIL_TEMPLATE'] = trim($arFields['EMAIL_TEMPLATE']); $arParams['NOTIFY_TAG'] = isset($arFields['NOTIFY_TAG'])? $arFields['NOTIFY_TAG']: ''; if (!empty($arParams['NOTIFY_TAG'])) { $lastMessages = BitrixImModelMessageTable::getList([ 'select' => ['ID', 'AUTHOR_ID'], 'filter' => [ '=NOTIFY_TAG' => $arParams['NOTIFY_TAG'], '=CHAT_ID' => $arParams['CHAT_ID'], ] ])->fetchAll(); // If we have other notifications with the same tag, // we need to get USERS from the old notifications // then merge it with AUTHOR_ID or create new USERS array with AUTHOR_ID // then delete old notifications. if (count($lastMessages) > 0) { foreach ($lastMessages as $lastMessage) { $lastMessage['AUTHOR_ID'] = (int)$lastMessage['AUTHOR_ID']; $lastMessageParams = CIMMessageParam::Get($lastMessage['ID']); if (empty($lastMessageParams['USERS']) && (int)$arFields['FROM_USER_ID'] !== $lastMessage['AUTHOR_ID']) { $arFields['PARAMS']['USERS'] = [$lastMessage['AUTHOR_ID']]; } else { $lastMessageParams['USERS'][] = $lastMessage['AUTHOR_ID']; $arFields['PARAMS']['USERS'] = array_unique($lastMessageParams['USERS']); $index = array_search((int)$arFields['FROM_USER_ID'], $arFields['PARAMS']['USERS'], true); if ($index !== false) { array_splice($arFields['PARAMS']['USERS'], $index, 1); } } CIMNotify::Delete($lastMessage['ID']); } } } $arParams['NOTIFY_SUB_TAG'] = isset($arFields['NOTIFY_SUB_TAG'])? $arFields['NOTIFY_SUB_TAG']: ''; if (isset($arFields['NOTIFY_TITLE']) && trim($arFields['NOTIFY_TITLE']) <> '') $arParams['NOTIFY_TITLE'] = trim($arFields['NOTIFY_TITLE']); if ($arParams['NOTIFY_TYPE'] == IM_NOTIFY_CONFIRM) { if (isset($arFields['NOTIFY_BUTTONS'])) { foreach ($arFields['NOTIFY_BUTTONS'] as $key => $arButtons) { if (is_array($arButtons)) { if (isset($arButtons['TITLE']) && $arButtons['TITLE'] <> '' && isset($arButtons['VALUE']) && $arButtons['VALUE'] <> '' && isset($arButtons['TYPE']) && $arButtons['TYPE'] <> '') { $arButtons['TITLE'] = htmlspecialcharsbx($arButtons['TITLE']); $arButtons['VALUE'] = htmlspecialcharsbx($arButtons['VALUE']); $arButtons['TYPE'] = htmlspecialcharsbx($arButtons['TYPE']); $arFields['NOTIFY_BUTTONS'][$key] = $arButtons; } else unset($arFields['NOTIFY_BUTTONS'][$key]); } else unset($arFields['NOTIFY_BUTTONS'][$key]); } } else { $arFields['NOTIFY_BUTTONS'] = Array( Array('TITLE' => GetMessage('IM_ERROR_BUTTON_ACCEPT'), 'VALUE' => 'Y', 'TYPE' => 'accept'), Array('TITLE' => GetMessage('IM_ERROR_BUTTON_CANCEL'), 'VALUE' => 'N', 'TYPE' => 'cancel'), ); } $arParams['NOTIFY_BUTTONS'] = serialize($arFields["NOTIFY_BUTTONS"]); if (isset($arParams['NOTIFY_TAG']) && $arParams['NOTIFY_TAG'] <> '') CIMNotify::DeleteByTag($arParams['NOTIFY_TAG']); } if ($skipAdd) { $messageID = time(); } else { $result = BitrixImModelMessageTable::add($arParams); $messageID = intval($result->getId()); if ($messageID <= 0) return false; if (empty($arFields['PARAMS'])) { CIMMessageParam::UpdateTimestamp($messageID, $arParams['CHAT_ID']); } else { CIMMessageParam::Set($messageID, $arFields['PARAMS']); } /*$counter = CIMNotify::GetCounter($chatId); if ($counter > 100) { $counter += 1; } else { $counter = CIMNotify::GetRealCounter($chatId); }*/ /*$DB->Query(" UPDATE b_im_relation SET STATUS = '".IM_STATUS_UNREAD."', COUNTER = {$counter} WHERE USER_ID = ".intval($arFields['TO_USER_ID'])." AND MESSAGE_TYPE = '".IM_MESSAGE_SYSTEM."' AND CHAT_ID = ".$chatId );*/ //BitrixImCounter::clearCache($arFields['TO_USER_ID']); $messageCount = BitrixImModelMessageTable::getList( [ 'select' => ['CNT'], 'filter' => ['=CHAT_ID' => $chatId], 'runtime' => [ new BitrixMainORMFieldsExpressionField('CNT', 'COUNT(*)') ] ] )->fetch(); BitrixImModelChatTable::update($chatId, Array( 'MESSAGE_COUNT' => $messageCount['CNT'], //'PREV_MESSAGE_ID' => new BitrixMainDBSqlExpression('?#', 'LAST_MESSAGE_ID'), 'LAST_MESSAGE_ID' => $messageID, //'LAST_MESSAGE_STATUS' => IM_MESSAGE_STATUS_RECEIVED )); CIMMessenger::SpeedFileDelete($arFields['TO_USER_ID'], IM_SPEED_NOTIFY); $relationObject = new BitrixImV2Relation([ 'USER_ID' => (int)$arFields['TO_USER_ID'], 'CHAT_ID' => $chatId, 'MESSAGE_TYPE' => IM_MESSAGE_SYSTEM, 'NOTIFY_BLOCK' => false, ]); $relationObject->setId(1); $message = new BitrixImV2Message($arParams); $message->setMessageId($messageID); $counter = (new BitrixImV2MessageReadService((int)$arFields['TO_USER_ID'])) ->onAfterNotificationSend($message, $relationObject)->getResult()['COUNTER'] ; } foreach(GetModuleEvents("im", "OnAfterNotifyAdd", true) as $arEvent) ExecuteModuleEventEx($arEvent, array(intval($messageID), $arFields)); $counter ??= null; if (CModule::IncludeModule('pull')) { $pullNotificationParams = CIMNotify::GetFormatNotify( [ 'ID' => $messageID, 'DATE_CREATE' => time(), 'FROM_USER_ID' => (int)$arFields['FROM_USER_ID'], 'MESSAGE' => $arParams['MESSAGE'], 'PARAMS' => self::PrepareParamsForPull($arFields['PARAMS']), 'NOTIFY_ONLY_FLASH' => $skipAdd, 'NOTIFY_LINK' => $arFields['NOTIFY_LINK'] ?? null, 'NOTIFY_MODULE' => $arParams['NOTIFY_MODULE'], 'NOTIFY_EVENT' => $arParams['NOTIFY_EVENT'], 'NOTIFY_TAG' => $arParams['NOTIFY_TAG'], 'NOTIFY_TYPE' => $arParams['NOTIFY_TYPE'], 'NOTIFY_BUTTONS' => $arParams['NOTIFY_BUTTONS'] ?? serialize([]), 'NOTIFY_TITLE' => $arParams['NOTIFY_TITLE'] ?? '', 'COUNTER' => $counter, ] ); // We shouldn't send push, if it is disabled in notification settings. $needPush = CIMSettings::GetNotifyAccess( $arFields['TO_USER_ID'], $arFields['NOTIFY_MODULE'], $arFields['NOTIFY_EVENT'], CIMSettings::CLIENT_PUSH ); if ($needPush) { // we prepare push params ONLY if there are no ADVANCED_PARAMS from outside. // If ADVANCED_PARAMS exists we must not change them. if (isset($arFields['PUSH_PARAMS']['ADVANCED_PARAMS'])) { $advancedParams = $arFields['PUSH_PARAMS']['ADVANCED_PARAMS']; unset($arFields['PUSH_PARAMS']['ADVANCED_PARAMS']); } else { $advancedParams = self::prepareAdvancedParamsForNotificationPush( $pullNotificationParams, $arFields['PUSH_MESSAGE'] ?? null ); } BitrixPullPush::add( $arFields['TO_USER_ID'], [ 'module_id' => $arParams['NOTIFY_MODULE'], 'push' => [ 'type' => $arFields['NOTIFY_EVENT'], 'message' => $arFields['PUSH_MESSAGE'] ?? null, 'params' => $arFields['PUSH_PARAMS'] ?? ['TAG' => 'IM_NOTIFY'], 'advanced_params' => $advancedParams, 'important' => isset($arFields['PUSH_IMPORTANT']) && $arFields['PUSH_IMPORTANT'] === 'Y' ? 'Y': 'N', 'tag' => $arParams['NOTIFY_TAG'], 'sub_tag' => $arParams['NOTIFY_SUB_TAG'], 'app_id' => $arParams['PUSH_APP_ID'] ?? '', ] ] ); } if (!$skipFlash) { BitrixPullEvent::add( $arFields['TO_USER_ID'], [ 'module_id' => 'im', 'command' => 'notifyAdd', 'params' => $pullNotificationParams, 'extra' => BitrixImCommon::getPullExtra() ] ); } } if (!$skipAdd) { BitrixImModelMessageTable::indexRecord($messageID); } return $messageID; } else { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID"); return false; } } else { $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_TYPE"), "MESSAGE_TYPE"); return false; } }