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;
}
}