1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
im_messenger.php
См. документацию.
1<?
20
21IncludeModuleLangFile(__FILE__);
22
24{
25 private $user_id = 0;
26 private static $enableMessageCheck = 1;
27
28 const MESSAGE_LIMIT = 20000;
29
30 function __construct($user_id = false)
31 {
32 global $USER;
33 $this->user_id = intval($user_id);
34 if ($this->user_id == 0)
35 $this->user_id = intval($USER->GetID());
36 }
37
128 public static function Add($arFields)
129 {
130 $v2SendEnabled = \Bitrix\Main\Config\Option::get('im', 'v2_send_enabled', 'Y');
131 if ($v2SendEnabled === 'Y' && $arFields['MESSAGE_TYPE'] !== 'S')
132 {
133 $messageObject = self::getMessageObject($arFields);
134
135 $config = new \Bitrix\Im\V2\Message\Send\SendingConfig($arFields);
136
137 $chat = $messageObject->getChat()->withContextUser($messageObject->getContext()->getUserId());
138
139 if ($chat instanceof \Bitrix\Im\V2\Chat\NullChat)
140 {
141 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID");
142
143 return false;
144 }
145
146 if (
147 !$messageObject->isSystem()
148 && !$config->convertMode()
149 && !$config->skipUserCheck()
150 && $messageObject->getAuthorId()
151 && !$chat->canDo(\Bitrix\Im\V2\Permission\Action::Send)
152 )
153 {
154 if ($arFields['MESSAGE_TYPE'] === Chat::IM_TYPE_PRIVATE)
155 {
156 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CANCELED"), "ERROR_NO_ACCESS");
157 }
158 else
159 {
160 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED");
161 }
162
163 return false;
164 }
165
166 $result = $chat->sendMessage($messageObject, $config);
167
168 if (!$result->isSuccess())
169 {
170 self::throwLegacyExceptionFromErrors($result->getErrors());
171
172 return false;
173 }
174
175 if (($arFields['WAIT_FULL_EXECUTION'] ?? 'Y') === 'Y')
176 {
177 $result->getPromise()?->wait();
178 }
179
180 return $result->getMessageId() ?? false;
181 }
182
183 global $DB;
184
185 $templateId = $arFields['TEMPLATE_ID'] ?? '';
186 if (
187 $arFields['MESSAGE_TYPE'] !== IM_MESSAGE_SYSTEM
189 )
190 {
191 $messageUuid = new Message\Uuid($templateId);
192 $uuidAddResult = $messageUuid->add();
193 // if it is false, then UUID already exists
194 if (!$uuidAddResult)
195 {
196 $messageIdByUuid = $messageUuid->getMessageId();
197 // if we got message_id, then message already exists, and we don't need to add it, so return with ID.
198 if (!is_null($messageIdByUuid))
199 {
200 return $messageIdByUuid;
201 }
202
203 // if there is no message_id and entry date is expired,
204 // then update date_create and return false to delay next sending on the client.
205 if (!$messageUuid->updateIfExpired())
206 {
207 return false;
208 }
209 }
210 }
211
212 if (isset($arFields['DIALOG_ID']) && !empty($arFields['DIALOG_ID']))
213 {
214 if (\Bitrix\Im\Common::isChatId($arFields['DIALOG_ID']))
215 {
216 $arFields['TO_CHAT_ID'] = \Bitrix\Im\Dialog::getChatId($arFields['DIALOG_ID']);
217 if (!isset($arFields['MESSAGE_TYPE']))
218 {
219 $arFields['MESSAGE_TYPE'] = IM_MESSAGE_CHAT;
220 }
221 }
222 else
223 {
224 $arFields['TO_USER_ID'] = intval($arFields['DIALOG_ID']);
225 $arFields['MESSAGE_TYPE'] = IM_MESSAGE_PRIVATE;
226 }
227 }
228
229 if (isset($arFields['TITLE']) && !isset($arFields['NOTIFY_TITLE']))
230 $arFields['NOTIFY_TITLE'] = mb_substr($arFields['TITLE'], 0, 255);
231
232 if (isset($arFields['NOTIFY_MESSAGE']) && !isset($arFields['MESSAGE']))
233 $arFields['MESSAGE'] = $arFields['NOTIFY_MESSAGE'];
234
235 if (isset($arFields['NOTIFY_MESSAGE_OUT']) && !isset($arFields['MESSAGE_OUT']))
236 $arFields['MESSAGE_OUT'] = $arFields['NOTIFY_MESSAGE_OUT'];
237
238 if (isset($arFields['MESSAGE']))
239 {
240 $arFields['MESSAGE'] = trim(str_replace(Array('[BR]', '[br]', '#BR#'), "\n", $arFields['MESSAGE']));
241 if (mb_strlen($arFields['MESSAGE']) > self::MESSAGE_LIMIT + 6)
242 {
243 $arFields['MESSAGE'] = mb_substr($arFields['MESSAGE'], 0, self::MESSAGE_LIMIT).' (...)';
244 }
245 }
246
247 if (isset($arFields['MESSAGE']) && ($arFields['SYSTEM'] ?? 'N') !== 'Y')
248 {
249 $arFields['MESSAGE'] = Text::filterUserBbCodes((string)$arFields['MESSAGE'], (int)$arFields['FROM_USER_ID']);
250 }
251
252 $isImportant = isset($arFields['IS_IMPORTANT']) && $arFields['IS_IMPORTANT'] === 'Y' ? 'Y' : 'N';
253
254 $arFields['MESSAGE_OUT'] = isset($arFields['MESSAGE_OUT'])? trim($arFields['MESSAGE_OUT']): "";
255
256 $arFields['URL_PREVIEW'] = isset($arFields['URL_PREVIEW']) && $arFields['URL_PREVIEW'] == 'N'? 'N': 'Y';
257 $arFields['SKIP_URL_INDEX'] ??= 'N';
258 $arFields['SKIP_COUNTER_INCREMENTS'] ??= 'N';
259
260 $bConvert = false;
261 if (isset($arFields['CONVERT']) && $arFields['CONVERT'] == 'Y')
262 $bConvert = true;
263
264 if (!isset($arFields['PARAMS']) || !is_array($arFields['PARAMS']))
265 {
266 $arFields['PARAMS'] = Array();
267 }
268 if (!isset($arFields['EXTRA_PARAMS']))
269 {
270 $arFields['EXTRA_PARAMS'] = Array();
271 }
272
273 $incrementCounter = true;
274 /*
275 if (isset($arFields['INCREMENT_COUNTER']) && $arFields['INCREMENT_COUNTER'] != 'Y')
276 {
277 if ($arFields['INCREMENT_COUNTER'] == 'N')
278 {
279 $incrementCounter = Array();
280 $arFields['PARAMS']['NOTIFY'] = 'N';
281 }
282 else if (is_array($arFields['INCREMENT_COUNTER']))
283 {
284 $incrementCounter = array_values($arFields['INCREMENT_COUNTER']);
285 $arFields['PARAMS']['NOTIFY'] = empty($incrementCounter)? 'N': $incrementCounter;
286 }
287 }
288 */
289
290 if (!isset($arFields['MESSAGE_TYPE']))
291 $arFields['MESSAGE_TYPE'] = "";
292
293 if (!isset($arFields['NOTIFY_MODULE']))
294 $arFields['NOTIFY_MODULE'] = 'im';
295
296 if (!isset($arFields['NOTIFY_EVENT']))
297 $arFields['NOTIFY_EVENT'] = 'default';
298
299 if (isset($arFields['ATTACH']) || isset($arFields['PARAMS']['ATTACH']))
300 {
301 $attach = isset($arFields['ATTACH'])? $arFields['ATTACH']: $arFields['PARAMS']['ATTACH'];
302 if (is_object($attach))
303 {
304 $arFields['PARAMS']['ATTACH'] = Array($attach);
305 }
306 else if (is_array($attach))
307 {
308 $arFields['PARAMS']['ATTACH'] = $attach;
309 }
310 else
311 {
312 $arFields['PARAMS']['ATTACH'] = Array();
313 }
314 }
315 if (isset($arFields['FILES']))
316 {
317 if (is_array($arFields['FILES']))
318 {
319 $arFields['PARAMS']['FILE_ID'] = $arFields['FILES'];
320 }
321 else
322 {
323 $arFields['PARAMS']['FILE_ID'] = Array();
324 }
325 }
326 if (isset($arFields['KEYBOARD']) || isset($arFields['PARAMS']['KEYBOARD']))
327 {
328 $keyboard = isset($arFields['KEYBOARD'])? $arFields['KEYBOARD']: $arFields['PARAMS']['KEYBOARD'];
329 if (is_object($keyboard))
330 {
331 $arFields['PARAMS']['KEYBOARD'] = $keyboard;
332 }
333 else
334 {
335 $arFields['PARAMS']['KEYBOARD'] = Array();
336 }
337 }
338 if (isset($arFields['MENU']) || isset($arFields['PARAMS']['MENU']))
339 {
340 $menu = isset($arFields['MENU'])? $arFields['MENU']: $arFields['PARAMS']['MENU'];
341 if (is_object($menu))
342 {
343 $arFields['PARAMS']['MENU'] = $menu;
344 }
345 else
346 {
347 $arFields['PARAMS']['MENU'] = Array();
348 }
349 }
350
351 if (isset($arFields['FOR_USER_ID'])) // TODO create this feature in future
352 {
353 $arFields['PARAMS']['FOR_USER_ID'] = $arFields['FOR_USER_ID'];
354 }
355
356 $arFields['RECENT_ADD'] = isset($arFields['RECENT_ADD']) && $arFields['RECENT_ADD'] == 'N'? 'N': 'Y';
357 $arFields['SKIP_COMMAND'] = isset($arFields['SKIP_COMMAND']) && $arFields['SKIP_COMMAND'] == 'Y'? 'Y': 'N';
358 $arFields['SKIP_CONNECTOR'] = isset($arFields['SKIP_CONNECTOR']) && $arFields['SKIP_CONNECTOR'] == 'Y'? 'Y': 'N';
359 $arFields['IMPORTANT_CONNECTOR'] = isset($arFields['IMPORTANT_CONNECTOR']) && $arFields['IMPORTANT_CONNECTOR'] == 'Y'? 'Y': 'N';
360 $arFields['SILENT_CONNECTOR'] = isset($arFields['SILENT_CONNECTOR']) && $arFields['SILENT_CONNECTOR'] == 'Y'? 'Y': 'N';
361 if ($arFields['SILENT_CONNECTOR'] == 'Y')
362 {
363 $arFields['PARAMS']['CLASS'] = "bx-messenger-content-item-system";
364 if ($arFields['MESSAGE_TYPE'] === IM_MESSAGE_OPEN_LINE)
365 {
366 $arFields['PARAMS']['COMPONENT_ID'] = 'HiddenMessage';
367 }
368 }
369
370 $fakeRelation = (isset($arFields['FAKE_RELATION']) && $arFields['FAKE_RELATION'] > 0) ? (int)$arFields['FAKE_RELATION'] : false;
371 if (
372 !$fakeRelation
373 && $arFields['MESSAGE_TYPE'] === IM_MESSAGE_OPEN_LINE
374 && class_exists('\Bitrix\ImOpenLines\Relation')
375 )
376 {
377 $fakeRelation = (new \Bitrix\ImOpenLines\Relation((int)$arFields['TO_CHAT_ID']))->getRelationUserIds();
378 }
379
380 if (is_int($fakeRelation) && $fakeRelation > 0)
381 {
382 $fakeRelation = [$fakeRelation];
383 }
384
385 $arFields['URL_ATTACH'] = Array();
386 if ($arFields['MESSAGE_TYPE'] == IM_MESSAGE_SYSTEM)
387 {
388 if (!isset($arFields['NOTIFY_TYPE']) && intval($arFields['FROM_USER_ID']) > 0)
389 $arFields['NOTIFY_TYPE'] = IM_NOTIFY_FROM;
390 else if (!isset($arFields['NOTIFY_TYPE']))
391 $arFields['NOTIFY_TYPE'] = IM_NOTIFY_SYSTEM;
392
393 if (isset($arFields['NOTIFY_ANSWER']) && $arFields['NOTIFY_ANSWER'] == 'Y')
394 $arFields['PARAMS']['CAN_ANSWER'] = 'Y';
395
396 /*
397 $urlPrepare = self::PrepareUrl($arFields['MESSAGE']);
398 if ($urlPrepare['RESULT'])
399 {
400 if (empty($arFields['MESSAGE_OUT']))
401 {
402 $arFields['MESSAGE_OUT'] = $arFields['MESSAGE'];
403 }
404 $arFields['MESSAGE'] = $urlPrepare['MESSAGE'];
405 $arFields['PARAMS']['ATTACH'] = array_merge($arFields['PARAMS']['ATTACH'], $urlPrepare['ATTACH']);
406 }
407 */
408 }
409 else if ($arFields['URL_PREVIEW'] == 'Y')
410 {
411 $link = new CIMMessageLink();
412 $message = $arFields['MESSAGE'] ?? null;
413 $urlPrepare = $link->prepareInsert($message);
414 if ($urlPrepare['RESULT'])
415 {
416 if (empty($arFields['MESSAGE_OUT']))
417 {
418 $arFields['MESSAGE_OUT'] = $arFields['MESSAGE'];
419 }
420 $arFields['MESSAGE'] = $urlPrepare['MESSAGE'];
421
422 if (isset($arFields['PARAMS']['URL_ID']))
423 {
424 $arFields['PARAMS']['URL_ID'] = array_merge($arFields['PARAMS']['URL_ID'], $urlPrepare['URL_ID']);
425 }
426 else
427 {
428 $arFields['PARAMS']['URL_ID'] = $urlPrepare['URL_ID'];
429 }
430 $arFields['URL_ATTACH'] = $urlPrepare['ATTACH'];
431
432 if ($urlPrepare['MESSAGE_IS_LINK'])
433 {
434 $arFields['PARAMS']['URL_ONLY'] = 'Y';
435 }
436 }
437 }
438 else if (isset($arFields['PARAMS']['URL_ID']) && is_array($arFields['PARAMS']['URL_ID']))
439 {
440 $urlId = (int)(array_values($arFields['PARAMS']['URL_ID'])[0] ?? 0);
441 if ($urlId !== 0)
442 {
444 if ($url !== null)
445 {
446 $arFields['URL_ATTACH'][] = $url->getUrlAttach();
447 }
448 }
449 }
450
451 if (isset($arFields['NOTIFY_EMAIL_TEMPLATE']) && !isset($arFields['EMAIL_TEMPLATE']))
452 $arFields['EMAIL_TEMPLATE'] = $arFields['NOTIFY_EMAIL_TEMPLATE'];
453
454 if (!isset($arFields['AUTHOR_ID']))
455 {
456 $arFields['AUTHOR_ID'] = isset($arFields['FROM_USER_ID']) ? (int)$arFields['FROM_USER_ID'] : 0;
457 }
458
459 foreach(GetModuleEvents("im", "OnBeforeMessageNotifyAdd", true) as $arEvent)
460 {
462 if($result===false || isset($result['result']) && $result['result'] === false)
463 {
464 $reason = self::GetReasonForMessageSendError($arFields['MESSAGE_TYPE'], $result['reason']);
465 $GLOBALS["APPLICATION"]->ThrowException($reason, "ERROR_FROM_OTHER_MODULE");
466 return false;
467 }
468 }
469 if (!self::CheckFields($arFields))
470 {
471 return false;
472 }
473
474 if ($arFields['MESSAGE_TYPE'] != IM_MESSAGE_SYSTEM)
475 {
476 $message = $arFields['MESSAGE'] ?? null;
477 if ($arFields['URL_PREVIEW'] === 'Y')
478 {
480 foreach ($results as $result)
481 {
482 $arFields['PARAMS']['DATE_TEXT'][] = $result->getText();
483 $arFields['PARAMS']['DATE_TS'][] = $result->getDate()->getTimestamp();
484 }
485 }
486
488 {
489 $arFields['PARAMS']['LARGE_FONT'] = 'Y';
490 }
491 }
492
493 if (isset($arFields['COPILOT']) && is_array($arFields['COPILOT']))
494 {
495 if (isset($arFields['COPILOT'][Params::COPILOT_PROMPT_CODE]) && is_string($arFields['COPILOT'][Params::COPILOT_PROMPT_CODE]))
496 {
498 }
499 }
500
501
502 if ($arFields['MESSAGE_TYPE'] == IM_MESSAGE_PRIVATE)
503 {
504 $isSelfChat = false;
505 if (isset($arFields['TO_CHAT_ID']))
506 {
507 $chatId = $arFields['TO_CHAT_ID'];
508 $relations = CIMChat::GetRelationById($chatId, false, true, false);
509
510 $arFields['TO_USER_ID'] = $arFields['FROM_USER_ID'];
511 foreach ($relations as $rel)
512 {
513 if (
514 $arFields['TO_USER_ID']
515 && $rel['USER_ID'] == $arFields['FROM_USER_ID']
516 )
517 {
518 continue;
519 }
520
521 $arFields['TO_USER_ID'] = $rel['USER_ID'];
522 }
523 if ($arFields['FROM_USER_ID'] == $arFields['TO_USER_ID'])
524 {
525 $isSelfChat = true;
526 }
527 }
528 else
529 {
530 $arFields['FROM_USER_ID'] = intval($arFields['FROM_USER_ID']);
531 $arFields['TO_USER_ID'] = intval($arFields['TO_USER_ID']);
532
533 $chatId = CIMMessage::GetChatId($arFields['FROM_USER_ID'], $arFields['TO_USER_ID']);
534 if ($arFields['FROM_USER_ID'] == $arFields['TO_USER_ID'])
535 {
536 $isSelfChat = true;
537 }
538 }
539
540 if (!$bConvert && !\Bitrix\Im\Dialog::hasAccess($arFields['TO_USER_ID'], $arFields['FROM_USER_ID']))
541 {
542 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CANCELED"), "ERROR_NO_ACCESS");
543 return false;
544 }
545
546 if ($chatId > 0)
547 {
548 if (
549 ($arFields['SYSTEM'] ?? 'N') === 'N'
550 && !\Bitrix\Im\V2\Entity\User\User::getInstance($arFields['FROM_USER_ID'])->isBot()
551 && !(new TextFieldEnabled((int)$chatId))->get()
552 )
553 {
554 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CANCELED"), "TEXT_FIELD_DISABLED");
555 return false;
556 }
557
558 $chatData = \Bitrix\Im\Model\ChatTable::getById($chatId)->fetch();
559 $prevMessageId = intval($chatData['PREV_MESSAGE_ID']);
560
561 $arFields['CHAT_ID'] = $chatId;
562 $arFields = self::UploadFileFromText($arFields);
563 if (!$arFields)
564 {
565 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_LINES_SHARE_FILE"), "LINES_SHARE");
566 return false;
567 }
568
569 $arParams = Array();
570 $arParams['CHAT_ID'] = $chatId;
571 $arParams['AUTHOR_ID'] = intval($arFields['AUTHOR_ID']);
572 $arParams['MESSAGE'] = $arFields['MESSAGE'] ?? null;
573 $arParams['MESSAGE_OUT'] = $arFields['MESSAGE_OUT'];
574 $arParams['NOTIFY_MODULE'] = $arFields['NOTIFY_MODULE'];
575 $arParams['NOTIFY_EVENT'] = isset($arFields['SYSTEM']) && $arFields['SYSTEM'] === 'Y' ? 'private_system': 'private';
576
577 if (isset($arFields['IMPORT_ID']))
578 $arParams['IMPORT_ID'] = intval($arFields['IMPORT_ID']);
579
580 if (isset($arFields['MESSAGE_DATE']))
581 {
582 $arParams['DATE_CREATE'] = new Bitrix\Main\Type\DateTime($arFields['MESSAGE_DATE']);
583 }
584 $arFiles = Array();
585 $arFields['FILES'] = Array();
586 if (isset($arFields['PARAMS']['FILE_ID']))
587 {
588 foreach ($arFields['PARAMS']['FILE_ID'] as $fileId)
589 {
590 $arFiles[$fileId] = $fileId;
591 }
592 }
593 $arFields['FILES'] = CIMDisk::GetFiles($chatId, $arFiles, false);
594
595 $messageFiles = self::GetFormatFilesMessageOut($arFields['FILES']);
596 if ($messageFiles <> '')
597 {
598 $arParams['MESSAGE_OUT'] = $arParams['MESSAGE_OUT'] <> ''? $arParams['MESSAGE_OUT']."\n".$messageFiles: $messageFiles;
599 $arFields['MESSAGE_OUT'] = $arParams['MESSAGE_OUT'];
600 }
601
602 $result = \Bitrix\Im\Model\MessageTable::add($arParams);
603 $messageID = intval($result->getId());
604 if ($messageID <= 0)
605 return false;
606
607 if (isset($messageUuid))
608 {
609 $messageUuid->updateMessageId($messageID);
610 }
611
612 \Bitrix\Im\Model\ChatTable::update($chatId, Array(
613 'MESSAGE_COUNT' => new \Bitrix\Main\DB\SqlExpression('?# + 1', 'MESSAGE_COUNT'),
614 'PREV_MESSAGE_ID' => new \Bitrix\Main\DB\SqlExpression('?#', 'LAST_MESSAGE_ID'),
615 'LAST_MESSAGE_ID' => $messageID,
616 //'LAST_MESSAGE_STATUS' => IM_MESSAGE_STATUS_RECEIVED
617 ));
618
619 if ($chatData['PARENT_MID'])
620 {
621 CIMMessageParam::set($chatData['PARENT_MID'], Array(
622 'CHAT_MESSAGE' => $chatData['MESSAGE_COUNT']+1,
623 'CHAT_LAST_DATE' => new \Bitrix\Main\Type\DateTime()
624 ));
625 CIMMessageParam::SendPull($chatData['PARENT_MID'], Array('CHAT_MESSAGE', 'CHAT_LAST_DATE'));
626 }
627
628 if (!empty($arFields['PARAMS']))
629 {
630 CIMMessageParam::Set($messageID, $arFields['PARAMS']);
631 }
632
633 if (!empty($arFields['URL_ATTACH']))
634 {
635 if (isset($arFields['PARAMS']['ATTACH']))
636 {
637 $arFields['PARAMS']['ATTACH'] = array_merge($arFields['PARAMS']['ATTACH'], $arFields['URL_ATTACH']);
638 }
639 else
640 {
641 $arFields['PARAMS']['ATTACH'] = $arFields['URL_ATTACH'];
642 }
643 }
644
645 $relations = CIMChat::GetRelationById($chatId, false, true, false);
646 $message = new \Bitrix\Im\V2\Message($arParams);
647 $message->setParams($arFields['PARAMS'] ?? []);
648 $message->setMessageId($messageID);
649 foreach ($relations as $relation)
650 {
651 if (\Bitrix\Im\User::getInstance($relation['USER_ID'])->isBot())
652 {
653 // bot
654 }
655 else if (!\Bitrix\Im\User::getInstance($relation['USER_ID'])->isActive())
656 {
657 continue;
658 }
659
660 if (isset($arFields['RECENT_SKIP_AUTHOR']) && $relation['USER_ID'] == $arParams['AUTHOR_ID'])
661 {
662 continue;
663 }
664
665 $addToRecent = true;
666 if ($incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter))
667 {
668 $addToRecent = \CIMContactList::InRecent($relation['USER_ID'], $arFields['MESSAGE_TYPE'], $relation['CHAT_ID']);
669 }
670 if ($addToRecent)
671 {
672 CIMContactList::SetRecent(Array(
673 'ENTITY_ID' => $relation['USER_ID'] == $arFields['TO_USER_ID']? $arFields['FROM_USER_ID']: $arFields['TO_USER_ID'],
674 'MESSAGE_ID' => $messageID,
675 'CHAT_TYPE' => IM_MESSAGE_PRIVATE,
676 'CHAT_ID' => $relation['CHAT_ID'],
677 'RELATION_ID' => $relation['ID'],
678 'USER_ID' => $relation['USER_ID']
679 ));
680 }
681 }
682
683 if (!$bConvert)
684 {
685 $pullIncluded = CModule::IncludeModule("pull");
686 $pullServerActive = $pullIncluded && CPullOptions::GetNginxStatus();
687 $relations = \Bitrix\Im\Chat::getRelation($chatId, Array(
688 //'REAL_COUNTERS' => 'Y',
689 'WITHOUT_COUNTERS' => 'Y',
690 'USER_DATA' => 'Y',
691 ));
692 $relationCollection = new RelationCollection();
693 foreach ($relations as $id => $relation)
694 {
695 if (\Bitrix\Im\User::getInstance($relation["USER_ID"])->isBot())
696 {
697 // bot
698 }
699 else if ($relation['USER_DATA']['ACTIVE'] == 'N')
700 {
701 continue;
702 }
703
704 $relationObject = new Relation([
705 'USER_ID' => (int)$relation['USER_ID'],
706 'CHAT_ID' => $relation['CHAT_ID'],
707 'MESSAGE_TYPE' => $relation['MESSAGE_TYPE'],
708 'NOTIFY_BLOCK' => $relation['NOTIFY_BLOCK'] === 'Y',
709 ]);
710 $relationObject->setId((int)$relation['ID']);
711 $relationCollection->add($relationObject);
712 if ($isSelfChat || $relation["USER_ID"] == $arFields["FROM_USER_ID"])
713 {
714 $relations[$id]['COUNTER'] = 0;
715 $relationUpdate = array(
716 //"STATUS" => IM_STATUS_READ,
717 //"MESSAGE_STATUS" => IM_MESSAGE_STATUS_RECEIVED,
718 //"UNREAD_ID" => $messageID,
719 //"COUNTER" => 0,
720 "LAST_ID" => $messageID,
721 "LAST_SEND_MESSAGE_ID" => $messageID,
722 //"LAST_READ" => new Bitrix\Main\Type\DateTime(),
723 );
724 /*if (!$pullServerActive)
725 {
726 unset($relationUpdate['STATUS']);
727 unset($relationUpdate['LAST_ID']);
728 }*/
729 if ($pullServerActive)
730 {
731 \Bitrix\Im\Model\RelationTable::update($relation["ID"], $relationUpdate);
732 }
733 }
734 else
735 {
736 /*$updateRelation = array(
737 "STATUS" => IM_STATUS_UNREAD,
738 "MESSAGE_STATUS" => IM_MESSAGE_STATUS_RECEIVED,
739 "UNREAD_ID" => $messageID,
740 "COUNTER" => $relation['COUNTER'],
741 );
742 if ($relation["UNREAD_ID"])
743 {
744 unset($updateRelation['UNREAD_ID']);
745 }
746 if ($incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter))
747 {
748 unset($updateRelation['COUNTER']);
749 }
750
751 \Bitrix\Im\Model\RelationTable::update($relation["ID"], $updateRelation);*/
752 }
753
754 //\Bitrix\Im\Counter::clearCache($relation['USER_ID']);
755 }
756 $counters = (new ReadService((int)$arFields["FROM_USER_ID"]))
757 ->onAfterMessageSend($message, $relationCollection, $arFields['SKIP_COUNTER_INCREMENTS'] === 'Y')
758 ->getResult()['COUNTERS']
759 ;
760
761 $importantFor = self::getMentionUsers($arParams['MESSAGE'] ?? '');
762
765 $relationCollection->getUserIds()
766 );
769 $relationCollection->getUserIds()
770 );
771
772 if (CModule::IncludeModule("pull") && ($arFields['SKIP_PULL'] ?? 'N') !== 'Y')
773 {
774 $arParams['FROM_USER_ID'] = $arFields['FROM_USER_ID'];
775 $arParams['TO_USER_ID'] = $arFields['TO_USER_ID'];
776
777 $pullMessage = Array(
778 'module_id' => 'im',
779 'command' => 'message',
780 'params' => CIMMessage::GetFormatMessage(Array(
781 'ID' => $messageID,
782 'TEMPLATE_ID' => $arFields['TEMPLATE_ID'] ?? null,
783 'FILE_TEMPLATE_ID' => $arFields['FILE_TEMPLATE_ID'] ?? null,
784 'PREV_ID' => self::getRealPrevId($messageID, $chatId),
785 'CHAT_ID' => $chatId,
786 'TO_USER_ID' => $arParams['TO_USER_ID'],
787 'FROM_USER_ID' => $arParams['FROM_USER_ID'],
788 'SYSTEM' => isset($arFields['SYSTEM']) && $arFields['SYSTEM'] === 'Y' ? 'Y' : 'N',
789 'MESSAGE' => $arParams['MESSAGE'],
790 'DATE_CREATE' => time(),
791 'PARAMS' => self::PrepareParamsForPull($arFields['PARAMS']),
792 'FILES' => $arFields['FILES'],
793 'NOTIFY' => $incrementCounter,
794 'IMPORTANT_FOR' => $importantFor,
795 'IS_IMPORTANT' => $isImportant,
796 )),
797 'extra' => \Bitrix\Im\Common::getPullExtra()
798 );
799
800 $pullMessageTo = $pullMessage;
801 $pullMessageTo['params']['dialogId'] = $arParams['FROM_USER_ID'];
802
803 $pullMessageFrom = $pullMessage;
804 $pullMessageFrom['params']['dialogId'] = $arParams['TO_USER_ID'];
805
806 $pullMessageFrom['params']['counter'] = $counters[(int)$arParams['FROM_USER_ID']] ?? 0;
807 \Bitrix\Pull\Event::add($arParams['FROM_USER_ID'], $pullMessageFrom);
808
809 if ($arParams['FROM_USER_ID'] != $arParams['TO_USER_ID'])
810 {
811 $pullMessageTo['params']['counter'] = $counters[(int)$arParams['TO_USER_ID']] ?? 0;
812 \Bitrix\Pull\Event::add($arParams['TO_USER_ID'], $pullMessageTo);
813
814 $pullMessageTo = self::PreparePushForPrivate($pullMessageTo);
815 $pullMessageFrom = self::PreparePushForPrivate($pullMessageFrom);
816
817 if (
818 !isset($arFields['PUSH'])
819 || isset($arFields['PUSH']) && $arFields['PUSH'] === 'Y'
820 )
821 {
822 if (isset($arFields['MESSAGE_PUSH']))
823 {
824 $pullMessageTo['push']['message'] = $arFields['MESSAGE_PUSH'];
825 $pullMessageTo['push']['advanced_params']['senderMessage'] = $arFields['MESSAGE_PUSH'];
826 $pullMessageFrom['push']['message'] = $arFields['MESSAGE_PUSH'];
827 $pullMessageFrom['push']['advanced_params']['senderMessage'] = $arFields['MESSAGE_PUSH'];
828 }
829
830 $pullMessageTo['push']['advanced_params']['counter'] = $counters[$arParams['TO_USER_ID']] ?? 0;
831 \Bitrix\Pull\Push::add($arParams['TO_USER_ID'], $pullMessageTo);
832
833 $pullMessageFrom['push']['advanced_params']['counter'] = $counters[$arParams['FROM_USER_ID']] ?? 0;
834 \Bitrix\Pull\Push::add($arParams['FROM_USER_ID'], array_merge_recursive($pullMessageFrom, ['push' => [
835 'skip_users' => [$arParams['FROM_USER_ID']],
836 'advanced_params' => [
837 "notificationsToCancel" => ['IM_MESS'],
838 ],
839 'send_immediately' => 'Y',
840 ]]));
841 }
842 }
843 }
844
845 foreach(GetModuleEvents("im", "OnAfterMessagesAdd", true) as $arEvent)
846 ExecuteModuleEventEx($arEvent, array(intval($messageID), $arFields));
847
848 $arFields['COMMAND_CONTEXT'] = 'TEXTAREA';
850 if (!$result)
851 {
852 \Bitrix\Im\Bot::onMessageAdd(intval($messageID), $arFields);
853 }
854
855 if ($arFields['SKIP_URL_INDEX'] !== 'Y')
856 {
857 (new \Bitrix\Im\V2\Link\Url\UrlService())->saveUrlsFromMessage($message);
858 }
859
860 $allFiles = self::getFilesFromMessage(
861 $arFields['FILE_MODELS'] ?? [],
862 $arFields['FILES_FROM_TEXT'] ?? [],
863 $arFields['PARAMS'] ?? []
864 );
865
866 (new \Bitrix\Im\V2\Link\File\FileService())->saveFilesFromMessage($allFiles, $message);
867 }
868
870 (new MessageAnalytics($message))->addSendMessage();
871
872 return $messageID;
873 }
874 else
875 {
876 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID");
877 return false;
878 }
879 }
880 else if (in_array($arFields['MESSAGE_TYPE'], CIMChat::getGroupTypesExtra()))
881 {
882 $arFields['SKIP_USER_CHECK'] = isset($arFields['SKIP_USER_CHECK']) && $arFields['SKIP_USER_CHECK'] == 'Y'? 'Y': 'N';
883 $arFields['FROM_USER_ID'] = isset($arFields['FROM_USER_ID']) ? (int)$arFields['FROM_USER_ID'] : 0;
884 $chatId = 0;
885 $systemMessage = false;
886 if (isset($arFields['SYSTEM']) && $arFields['SYSTEM'] == 'Y')
887 {
888 $strSql = "
889 SELECT
890 C.ID CHAT_ID,
891 C.PARENT_ID CHAT_PARENT_ID,
892 C.PARENT_MID CHAT_PARENT_MID,
893 C.TITLE CHAT_TITLE,
894 C.AUTHOR_ID CHAT_AUTHOR_ID,
895 C.TYPE CHAT_TYPE,
896 C.AVATAR CHAT_AVATAR,
897 C.COLOR CHAT_COLOR,
898 C.ENTITY_TYPE CHAT_ENTITY_TYPE,
899 C.ENTITY_ID CHAT_ENTITY_ID,
900 C.ENTITY_DATA_1 CHAT_ENTITY_DATA_1,
901 C.ENTITY_DATA_2 CHAT_ENTITY_DATA_2,
902 C.ENTITY_DATA_3 CHAT_ENTITY_DATA_3,
903 C.EXTRANET CHAT_EXTRANET,
904 C.PREV_MESSAGE_ID CHAT_PREV_MESSAGE_ID,
905 C.CAN_POST CHAT_CAN_POST,
906 '1' RID,
907 'Y' IS_MANAGER,
908 '0' RELATION_ID
909 FROM b_im_chat C
910 WHERE C.ID = ".intval($arFields['TO_CHAT_ID'])."
911 ";
912 $systemMessage = true;
913 }
914 else
915 {
916 $strSql = "
917 SELECT
918 C.ID as CHAT_ID,
919 C.PARENT_ID as CHAT_PARENT_ID,
920 C.PARENT_MID as CHAT_PARENT_MID,
921 C.TITLE as CHAT_TITLE,
922 C.AUTHOR_ID as CHAT_AUTHOR_ID,
923 C.TYPE as CHAT_TYPE,
924 C.AVATAR as CHAT_AVATAR,
925 C.COLOR as CHAT_COLOR,
926 C.ENTITY_TYPE as CHAT_ENTITY_TYPE,
927 C.ENTITY_ID as CHAT_ENTITY_ID,
928 C.ENTITY_DATA_1 as CHAT_ENTITY_DATA_1,
929 C.ENTITY_DATA_2 as CHAT_ENTITY_DATA_2,
930 C.ENTITY_DATA_3 as CHAT_ENTITY_DATA_3,
931 C.EXTRANET as CHAT_EXTRANET,
932 C.PREV_MESSAGE_ID as CHAT_PREV_MESSAGE_ID,
933 C.CAN_POST as CHAT_CAN_POST,
934 R.USER_ID as RID,
935 R.MANAGER as IS_MANAGER,
936 R.ID as RELATION_ID
937 FROM b_im_chat C
938 LEFT JOIN b_im_relation R ON R.CHAT_ID = C.ID AND R.USER_ID = ".$arFields['FROM_USER_ID']."
939 WHERE C.ID = ".intval($arFields['TO_CHAT_ID'])."
940 ";
941 }
942
943 $dbRes = $DB->Query($strSql);
944 if ($arRes = $dbRes->Fetch())
945 {
946 $chatId = intval($arRes['CHAT_ID']);
947 $chatTitle = htmlspecialcharsbx(Text::decodeEmoji($arRes['CHAT_TITLE']));
948 $chatAuthorId = intval($arRes['CHAT_AUTHOR_ID']);
949 $chatParentId = intval($arRes['CHAT_PARENT_ID']);
950 $chatParentMid = intval($arRes['CHAT_PARENT_MID']);
951 $chatExtranet = $arRes['CHAT_EXTRANET'] == 'Y';
952 $arRes['CHAT_TYPE'] = trim($arRes['CHAT_TYPE']);
953 $arFields['MESSAGE_TYPE'] = $arRes['CHAT_TYPE'];
954 $prevMessageId = intval($arRes['CHAT_PREV_MESSAGE_ID']);
955 $importantPush = $arRes['CHAT_ENTITY_TYPE'] == 'ANNOUNCEMENT';
956
957 if ($arFields['SKIP_USER_CHECK'] == 'N')
958 {
959 $isSystem = ($arFields['SYSTEM'] ?? 'N') === 'Y';
960 if ((int)$arFields['FROM_USER_ID'] !== 0 && !$isSystem)
961 {
962 $userRole = Chat::ROLE_MEMBER;
963 if ($arRes['IS_MANAGER'] === 'Y')
964 {
965 $userRole = Chat::ROLE_MANAGER;
966 }
967 if ((int)$arRes['CHAT_AUTHOR_ID'] === (int)$arFields['FROM_USER_ID'])
968 {
969 $userRole = Bitrix\Im\V2\Chat::ROLE_OWNER;
970 }
971 if (!\Bitrix\Im\V2\Permission::compareRole($userRole, $arRes['CHAT_CAN_POST'] ?? ''))
972 {
973 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED");
974 return false;
975 }
976 }
977
978 if ($arRes['CHAT_ENTITY_TYPE'] == 'ANNOUNCEMENT' && $arRes['IS_MANAGER'] !== 'Y')
979 {
980 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED");
981 return false;
982 }
983
984 if ($arRes['CHAT_TYPE'] == IM_MESSAGE_OPEN)
985 {
987 {
988 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED");
989 return false;
990 }
991 else if (intval($arRes['RID']) <= 0)
992 {
993 if (\Bitrix\Im\User::getInstance($arFields['FROM_USER_ID'])->isExtranet())
994 {
995 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED");
996 return false;
997 }
998 else
999 {
1000 $chat = new CIMChat(0);
1001 $chat->AddUser($chatId, $arFields['FROM_USER_ID']);
1002 }
1003 }
1004 }
1005 else if (intval($arRes['RID']) <= 0)
1006 {
1007 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED");
1008 return false;
1009 }
1010 }
1011 }
1012 else
1013 {
1014 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "CANCELED");
1015 return false;
1016 }
1017
1018 if ($chatId > 0)
1019 {
1020 foreach(GetModuleEvents("im", "OnBeforeChatMessageAdd", true) as $arEvent)
1021 {
1023 if($result===false || isset($result['result']) && $result['result'] === false)
1024 {
1025 $reason = self::GetReasonForMessageSendError($arFields['MESSAGE_TYPE'], $result['reason']);
1026 $GLOBALS["APPLICATION"]->ThrowException($reason, "ERROR_FROM_OTHER_MODULE");
1027 return false;
1028 }
1029 if (isset($result['fields']))
1030 {
1031 $arFields = $result['fields'];
1032 }
1033 }
1034
1035 if (
1036 ($arFields['SYSTEM'] ?? 'N') === 'N'
1037 && !\Bitrix\Im\V2\Entity\User\User::getInstance($arFields['FROM_USER_ID'])->isBot()
1038 && !(new TextFieldEnabled($chatId))->get()
1039 )
1040 {
1041 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_GROUP_CANCELED"), "TEXT_FIELD_DISABLED");
1042 return false;
1043 }
1044
1045 $chatObject = Chat::getInstance($chatId);
1046
1047 $chatId = intval($arRes['CHAT_ID']);
1048 $arFields['CHAT_ID'] = $chatId;
1049 $arFields = self::UploadFileFromText($arFields);
1050
1051 $arParams = Array();
1052 $arParams['CHAT_ID'] = $chatId;
1053 $arParams['AUTHOR_ID'] = $systemMessage? 0: intval($arFields['AUTHOR_ID']);
1054 $arParams['MESSAGE'] = $arFields['MESSAGE'] ?? null;
1055 $arParams['MESSAGE_OUT'] = $arFields['MESSAGE_OUT'];
1056 $arParams['NOTIFY_MODULE'] = 'im';
1057 $arParams['NOTIFY_EVENT'] = 'group';
1058
1059 if (isset($arFields['MESSAGE_DATE']))
1060 {
1061 $arParams['DATE_CREATE'] = new Bitrix\Main\Type\DateTime($arFields['MESSAGE_DATE']);
1062 }
1063
1064 $arFiles = Array();
1065 $arFields['FILES'] = Array();
1066
1067 if (isset($arFields['PARAMS']['FILE_ID']))
1068 {
1069 foreach ($arFields['PARAMS']['FILE_ID'] as $fileId)
1070 {
1071 $arFiles[$fileId] = $fileId;
1072 }
1073 }
1074 $arFields['FILES'] = CIMDisk::GetFiles($chatId, $arFiles, false);
1075 $messageFiles = self::GetFormatFilesMessageOut($arFields['FILES']);
1076 if ($messageFiles <> '')
1077 {
1078 $arParams['MESSAGE_OUT'] = $arParams['MESSAGE_OUT'] <> ''? $arParams['MESSAGE_OUT']."\n".$messageFiles: $messageFiles;
1079 $arFields['MESSAGE_OUT'] = $arParams['MESSAGE_OUT'];
1080 }
1081
1082 $result = \Bitrix\Im\Model\MessageTable::add($arParams);
1083 $messageID = intval($result->getId());
1084 if ($messageID <= 0)
1085 return false;
1086
1087 if (isset($messageUuid))
1088 {
1089 $messageUuid->updateMessageId($messageID);
1090 }
1091
1092 if (!empty($arFields['PARAMS']))
1093 {
1094 CIMMessageParam::Set($messageID, $arFields['PARAMS']);
1095 }
1096
1097 if (!empty($arFields['URL_ATTACH']))
1098 {
1099 if (isset($arFields['PARAMS']['ATTACH']))
1100 {
1101 $arFields['PARAMS']['ATTACH'] = array_merge($arFields['PARAMS']['ATTACH'], $arFields['URL_ATTACH']);
1102 }
1103 else
1104 {
1105 $arFields['PARAMS']['ATTACH'] = $arFields['URL_ATTACH'];
1106 }
1107 }
1108
1109 if (!$bConvert)
1110 {
1111 \Bitrix\Im\Model\ChatTable::update($chatId, Array(
1112 'MESSAGE_COUNT' => new \Bitrix\Main\DB\SqlExpression('?# + 1', 'MESSAGE_COUNT'),
1113 'PREV_MESSAGE_ID' => new \Bitrix\Main\DB\SqlExpression('?#', 'LAST_MESSAGE_ID'),
1114 'LAST_MESSAGE_ID' => $messageID,
1115 //'LAST_MESSAGE_STATUS' => IM_MESSAGE_STATUS_RECEIVED
1116 ));
1117
1118 $realPrevId = self::getRealPrevId($messageID, $chatId);
1119 $importantFor = self::getMentionUsers($arParams['MESSAGE'] ?? '');
1120 if ($arFields['MESSAGE_TYPE'] === Chat::IM_TYPE_COMMENT)
1121 {
1122 $chat = Chat::getInstance($chatId);
1123 $userToSubscribe = $importantFor;
1124 if ($chat instanceof \Bitrix\Im\V2\Chat\CommentChat)
1125 {
1126 $chat->subscribe(true, (int)$arFields['FROM_USER_ID']);
1127 $chat->subscribeUsers(true, $userToSubscribe, $realPrevId);
1128 }
1129 }
1130
1131 if ($chatParentMid)
1132 {
1133 $chatData = \Bitrix\Im\Model\ChatTable::getById($chatId)->fetch();
1134 CIMMessageParam::set($chatParentMid, Array(
1135 'CHAT_MESSAGE' => $chatData['MESSAGE_COUNT'],
1136 'CHAT_LAST_DATE' => new \Bitrix\Main\Type\DateTime()
1137 ));
1138 CIMMessageParam::SendPull($chatParentMid, Array('CHAT_MESSAGE', 'CHAT_LAST_DATE'));
1139 }
1140
1141 $arParams['FROM_USER_ID'] = $arFields['FROM_USER_ID'];
1142 $arParams['TO_CHAT_ID'] = $arFields['TO_CHAT_ID'];
1143
1144 $arBotInChat = Array();
1145 $parentRelations = null;
1146 if ($fakeRelation)
1147 {
1148 $allBots = \Bitrix\Im\Bot::getListCache();
1149 $relations = [];
1150 foreach ($fakeRelation as $fakeId)
1151 {
1152 $relations[$fakeId] = [
1153 'ID' => 0,
1154 'USER_ID' => $fakeId,
1155 'CHAT_ID' => $arFields['TO_CHAT_ID'],
1156 'MESSAGE_TYPE' => 'S',
1157 'NOTIFY_BLOCK' => 'N',
1158 'FROM_USER_ID' => $arFields['FROM_USER_ID'],
1159 'USER_DATA' =>
1160 [
1161 'ACTIVE' => 'Y',
1162 'EXTERNAL_AUTH_ID' => isset($allBots[$fakeId]) ? 'bot' : 'default',
1163 ]
1164 ];
1165 }
1166 }
1167 else
1168 {
1169 $filter = $arRes['CHAT_TYPE'] === Chat::IM_TYPE_COMMENT ? ['NOTIFY_BLOCK' => 'N'] : [];
1170 $relations = \Bitrix\Im\Chat::getRelation($chatId, Array(
1171 //'REAL_COUNTERS' => 'Y',
1172 'WITHOUT_COUNTERS' => 'Y',
1173 'USER_DATA' => 'Y',
1174 'SKIP_CONNECTOR' => $arRes['CHAT_ENTITY_TYPE'] == 'LINES'? 'Y': 'N',
1175 'FILTER' => $filter,
1176 ));
1177 if ($arRes['CHAT_TYPE'] === Chat::IM_TYPE_COMMENT)
1178 {
1179 [$relations, $parentRelations] = self::filterRelationsByParentRelations($relations, $chatParentId);
1180 }
1181 }
1182
1183 $extendedType = \Bitrix\Im\Chat::getType($arRes, false);
1184 $recentSections = \Bitrix\Im\V2\Recent\Config\RecentConfigManager::getInstance()->getRecentSectionsByChatExtendedType($extendedType);
1185 $shouldAddToRecent = !empty($recentSections);
1186 $isCounterIncrementAllowed = $shouldAddToRecent || $arFields['MESSAGE_TYPE'] === Chat::IM_TYPE_COMMENT;
1187
1188 $pullIncluded = CModule::IncludeModule("pull");
1189 $pullServerActive = $pullIncluded && CPullOptions::GetNginxStatus();
1190 $events = [];
1191
1192 $skippedRelations = [];
1193
1194 $pushUserSkip = [];
1195 $pushUserSend = [];
1196
1197 $relationCollection = new RelationCollection();
1198 foreach ($relations as $id => $relation)
1199 {
1200 if ($arFields['RECENT_ADD'] != 'Y')
1201 {
1202 $skippedRelations[$id] = true;
1203 continue;
1204 }
1205 if ($relation['USER_DATA']["EXTERNAL_AUTH_ID"] == \Bitrix\Im\Bot::EXTERNAL_AUTH_ID)
1206 {
1207 $arBotInChat[$relation["USER_ID"]] = $relation["USER_ID"];
1208 }
1209 else if ($relation['USER_DATA']['ACTIVE'] == 'N')
1210 {
1211 $skippedRelations[$id] = true;
1212 continue;
1213 }
1214
1215 $sessionId = 0;
1216 if ($arRes['CHAT_ENTITY_TYPE'] == "LINES")
1217 {
1218 if ($relation['USER_DATA']["EXTERNAL_AUTH_ID"] == 'imconnector')
1219 {
1220 $skippedRelations[$id] = true;
1221 continue;
1222 }
1223 if ($arRes['CHAT_ENTITY_DATA_1'])
1224 {
1225 $fieldData = explode("|", $arRes['CHAT_ENTITY_DATA_1']);
1226 $sessionId = intval($fieldData[5]);
1227 }
1228 }
1229
1230 $addToRecent = true;
1231 if ($incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter))
1232 {
1233 $addToRecent = \CIMContactList::InRecent($relation['USER_ID'], $arFields['MESSAGE_TYPE'], $relation['CHAT_ID']);
1234 }
1235
1236 if ($addToRecent && !$fakeRelation && $shouldAddToRecent)
1237 {
1238 CIMContactList::SetRecent([
1239 'ENTITY_ID' => $chatId,
1240 'MESSAGE_ID' => $messageID,
1241 'CHAT_TYPE' => $arFields['MESSAGE_TYPE'],
1242 'USER_ID' => $relation['USER_ID'],
1243 'CHAT_ID' => $relation['CHAT_ID'],
1244 'RELATION_ID' => $relation['ID'],
1245 'SESSION_ID' => $sessionId,
1246 ]);
1247 }
1248
1249 if (!$fakeRelation)
1250 {
1251 $relationObject = new Relation([
1252 'USER_ID' => (int)$relation['USER_ID'],
1253 'CHAT_ID' => $relation['CHAT_ID'],
1254 'MESSAGE_TYPE' => $relation['MESSAGE_TYPE'],
1255 'NOTIFY_BLOCK' => $relation['NOTIFY_BLOCK'] === 'Y',
1256 ]);
1257 $relationObject->setId((int)$relation['ID']);
1258 $relationCollection->add($relationObject);
1259 }
1260
1261 if ($relation["USER_ID"] == $arFields["FROM_USER_ID"])
1262 {
1263 $relations[$id]['COUNTER'] = $relation['COUNTER'] = 0;
1264
1265 $relationUpdate = array(
1266 //"STATUS" => IM_STATUS_READ,
1267 //"MESSAGE_STATUS" => IM_MESSAGE_STATUS_RECEIVED,
1268 //"COUNTER" => 0,
1269 //"UNREAD_ID" => $messageID,
1270 "LAST_ID" => $messageID,
1271 "LAST_SEND_MESSAGE_ID" => $messageID,
1272 //"LAST_READ" => new Bitrix\Main\Type\DateTime(),
1273 );
1274 /*if (!$pullServerActive)
1275 {
1276 unset($relationUpdate['STATUS']);
1277 unset($relationUpdate['LAST_ID']);
1278 }*/
1279 if ($pullServerActive)
1280 {
1281 \Bitrix\Im\Model\RelationTable::update($relation["ID"], $relationUpdate);
1282 }
1283 }
1284 else
1285 {
1286 /*$updateRelation = array(
1287 "STATUS" => IM_STATUS_UNREAD,
1288 "UNREAD_ID" => $messageID,
1289 "MESSAGE_STATUS" => IM_MESSAGE_STATUS_RECEIVED,
1290 "COUNTER" => $relation['COUNTER'],
1291 );
1292 if ($relation["UNREAD_ID"])
1293 {
1294 unset($updateRelation['UNREAD_ID']);
1295 }
1296 if ($incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter))
1297 {
1298 unset($updateRelation['COUNTER']);
1299 }
1300 \Bitrix\Im\Model\RelationTable::update($relation["ID"], $updateRelation);*/
1301 }
1302
1303 //\Bitrix\Im\Counter::clearCache($relation['USER_ID']);
1304
1305 if (!$pullIncluded)
1306 {
1307 continue;
1308 }
1309
1310 $sendPush = true;
1311 if ($relation['USER_ID'] == $arParams['FROM_USER_ID'])
1312 {
1313 CPushManager::DeleteFromQueueBySubTag($arParams['FROM_USER_ID'], 'IM_MESS');
1314 $sendPush = false;
1315 }
1316 else if ($relation['NOTIFY_BLOCK'] == 'Y' && !$importantPush)
1317 {
1318 $pushUserSkip[] = $relation['USER_ID'];
1319 $pushUserSend[] = $relation['USER_ID'];
1320 }
1321 else if (isset($arFields['PUSH']) && $arFields['PUSH'] === 'N')
1322 {
1323 $sendPush = false;
1324 }
1325 else
1326 {
1327 $pushUserSend[] = $relation['USER_ID'];
1328 }
1329 }
1330
1331 if (
1332 $arFields['MESSAGE_TYPE'] === Chat::IM_TYPE_COMMENT
1333 && $parentRelations !== null
1334 && $arFields['SKIP_COUNTER_INCREMENTS'] !== 'Y'
1335 )
1336 {
1337 $lastActivity = new \Bitrix\Main\Type\DateTime();
1338 Application::getInstance()->addBackgroundJob(
1339 static function () use ($arRes, $parentRelations, $lastActivity) {
1340 $chat = Chat::getInstance((int)$arRes['CHAT_PARENT_ID']);
1341 $chat->setRelations($parentRelations);
1342 \Bitrix\Im\Recent::raiseChat($chat, $parentRelations, $lastActivity);
1343 }
1344 );
1345 }
1346
1347 $message = new \Bitrix\Im\V2\Message($arParams);
1348 $message->setParams($arFields['PARAMS'] ?? []);
1349 $message->setMessageId($messageID);
1350 if ($shouldAddToRecent)
1351 {
1354 $relationCollection->getUserIds(),
1355 \Bitrix\Im\V2\Chat::getInstance($chatId)
1356 );
1359 $relationCollection->getUserIds(),
1360 \Bitrix\Im\V2\Chat::getInstance($chatId)
1361 );
1362 }
1363 $notify = $incrementCounter;
1364
1365 if ($arRes['CHAT_TYPE'] === Chat::IM_TYPE_COMMENT)
1366 {
1368 }
1369 if (!$shouldAddToRecent)
1370 {
1371 $notify = false;
1372 }
1373
1374 $pullMessage = [
1375 'module_id' => 'im',
1376 'command' => 'messageChat',
1377 'params' => CIMMessage::GetFormatMessage([
1378 'ID' => $messageID,
1379 'TEMPLATE_ID' => $arFields['TEMPLATE_ID'] ?? null,
1380 'FILE_TEMPLATE_ID' => $arFields['FILE_TEMPLATE_ID'] ?? null,
1381 'PREV_ID' => $realPrevId,
1382 'CHAT_ID' => $chatId,
1383 'TO_CHAT_ID' => $arParams['TO_CHAT_ID'],
1384 'FROM_USER_ID' => $arParams['FROM_USER_ID'],
1385 'MESSAGE' => $arParams['MESSAGE'],
1386 'SYSTEM' => ($arFields['SYSTEM'] ?? null) === 'Y' ? 'Y' : 'N',
1387 'DATE_CREATE' => time(),
1388 'PARAMS' => self::PrepareParamsForPull($arFields['PARAMS']),
1389 'FILES' => $arFields['FILES'],
1390 'EXTRA_PARAMS' => $arFields['EXTRA_PARAMS'],
1391 'COUNTER' => -1,
1392 'NOTIFY' => $notify,
1393 'IMPORTANT_FOR' => $importantFor,
1394 'IS_IMPORTANT' => $isImportant,
1395 ]),
1397 ];
1398
1399 if (!$fakeRelation)
1400 {
1401 $withoutCounters = $arFields['SKIP_COUNTER_INCREMENTS'] === 'Y' || !$isCounterIncrementAllowed;
1402 $counters = (new ReadService((int)$arFields["FROM_USER_ID"]))
1403 ->onAfterMessageSend($message, $relationCollection, $withoutCounters)
1404 ->getResult()['COUNTERS']
1405 ;
1406 }
1407 else
1408 {
1409 foreach ($fakeRelation as $fakeId)
1410 {
1411 $counters[$fakeId] = 1;
1412 if (
1413 isset($pullMessage['params']['userInChat'][$arParams['TO_CHAT_ID']])
1414 && !in_array($fakeId, $pullMessage['params']['userInChat'][$arParams['TO_CHAT_ID']]))
1415 {
1416 $pullMessage['params']['userInChat'][$arParams['TO_CHAT_ID']][] = $fakeId;
1417 }
1418 }
1419 }
1420
1421 foreach ($relations as $id => $relation)
1422 {
1423 $skippedRelation = $skippedRelations[$id] ?? null;
1424 if ($skippedRelation)
1425 {
1426 continue;
1427 }
1428 $events[$relation['USER_ID']] = $pullMessage;
1429 $events[$relation['USER_ID']]['params']['counter'] = $counters[$relation['USER_ID']] ?? 0;
1430 //$events[$relation['USER_ID']]['params']['counter'] = $incrementCounter !== true && !in_array($relation['USER_ID'], $incrementCounter)? $relation['PREVIOUS_COUNTER']: $relation['COUNTER'];
1431 $events[$relation['USER_ID']]['groupId'] = 'im_chat_'.$chatId.'_'.$messageID.'_'.$events[$relation['USER_ID']]['params']['counter'];
1432 }
1433
1434 if (($arFields['SYSTEM'] ?? null) !== 'Y')
1435 {
1436 self::SendMention([
1437 'CHAT_ID' => $chatId,
1438 'CHAT_TITLE' => $chatTitle,
1439 'CHAT_RELATION' => $relations,
1440 'CHAT_TYPE' => $arFields['MESSAGE_TYPE'],
1441 'CHAT_ENTITY_TYPE' => $arRes['CHAT_ENTITY_TYPE'],
1442 'CHAT_COLOR' => $arRes['CHAT_COLOR'],
1443 'MESSAGE' => $arParams['MESSAGE'],
1444 'FILES' => $arFields['FILES'],
1445 'FROM_USER_ID' => $arParams['FROM_USER_ID'],
1446 'MENTION_USERS' => $importantFor,
1447 'MESSAGE_OBJECT' => $messageObject,
1448 'MESSAGE_ID' => $messageID,
1449 ]);
1450 }
1451
1452 if ($pullIncluded && ($arFields['SKIP_PULL'] ?? 'N') !== 'Y')
1453 {
1454 $watchPullMessage = $pullMessage;
1455 $watchPullMessage['params']['message']['params']['NOTIFY'] = 'N';
1456 $watchPullMessage['extra']['is_shared_event'] = true;
1457 $watchPullMessage['params']['recentConfig']['sections'] = $chatObject->getRecentSectionsForGuest();
1458 if (self::needToSendPublicPull($arRes['CHAT_TYPE']))
1459 {
1460 CPullWatch::AddToStack('IM_PUBLIC_' . $chatId, $watchPullMessage);
1461 }
1462 if ($arRes['CHAT_TYPE'] === Chat::IM_TYPE_COMMENT)
1463 {
1464 CPullWatch::AddToStack('IM_PUBLIC_COMMENT_' . $chatParentId, $watchPullMessage);
1465 }
1466 if ($arRes['CHAT_TYPE'] === Chat::IM_TYPE_OPEN_CHANNEL)
1467 {
1469 }
1470
1471 $groups = self::GetEventByCounterGroup($events);
1472 foreach ($groups as $group)
1473 {
1474 \Bitrix\Pull\Event::add($group['users'], $group['event']);
1475
1476 $userList = array_intersect($pushUserSend, $group['users']);
1477 $needSendPush = !empty($userList) && self::needSendPush($arRes);
1478 if ($needSendPush)
1479 {
1480 $pushParams = $group['event'];
1481
1482 $pushParams = self::PreparePushForChat($pushParams);
1483
1484 if ($importantPush)
1485 {
1486 $pushParams['push']['important'] = 'Y';
1487 }
1488
1489 $pushParams['skip_users'] = $pushUserSkip;
1490
1491 if (isset($arFields['MESSAGE_PUSH']))
1492 {
1493 $pushParams['push']['message'] = $arFields['MESSAGE_PUSH'];
1494 $pushParams['push']['advanced_params']['senderMessage'] = $arFields['MESSAGE_PUSH'];
1495 }
1496 $pushParams['push']['advanced_params']['counter'] = $group['event']['params']['counter'];
1497
1498 \Bitrix\Pull\Push::add($userList, $pushParams);
1499 }
1500 }
1501 }
1502
1503 $arFields['CHAT_AUTHOR_ID'] = $chatAuthorId;
1504 $arFields['CHAT_ENTITY_TYPE'] = $arRes['CHAT_ENTITY_TYPE'];
1505 $arFields['CHAT_ENTITY_ID'] = $arRes['CHAT_ENTITY_ID'];
1506 $arFields['CHAT_ENTITY_DATA_1'] = $arRes['CHAT_ENTITY_DATA_1'];
1507 $arFields['CHAT_ENTITY_DATA_2'] = $arRes['CHAT_ENTITY_DATA_2'];
1508 $arFields['CHAT_ENTITY_DATA_3'] = $arRes['CHAT_ENTITY_DATA_3'];
1509 $arFields['BOT_IN_CHAT'] = $arBotInChat;
1510
1511 foreach (GetModuleEvents("im", "OnAfterMessagesAdd", true) as $arEvent)
1512 ExecuteModuleEventEx($arEvent, [intval($messageID), $arFields]);
1513
1514 if ($arRes['CHAT_ENTITY_TYPE'] && $arRes['CHAT_TYPE'] === Chat::IM_TYPE_CHAT)
1515 {
1516 $converter = new Converter(Converter::TO_CAMEL | Converter::UC_FIRST);
1517 $eventName = 'OnAfterMessagesAdd' . $converter->process($arRes['CHAT_ENTITY_TYPE']);
1518 $eventAfterMessageAddEntityChat = new \Bitrix\Main\Event('im', $eventName, $arFields);
1519 $eventAfterMessageAddEntityChat->send();
1520 }
1521
1522 $arFields['COMMAND_CONTEXT'] = 'TEXTAREA';
1523 $result = \Bitrix\Im\Command::onCommandAdd(intval($messageID), $arFields);
1524 if (!$result)
1525 {
1526 \Bitrix\Im\Bot::onMessageAdd(intval($messageID), $arFields);
1527 }
1528
1529 if ($arFields['SKIP_URL_INDEX'] !== 'Y')
1530 {
1531 (new \Bitrix\Im\V2\Link\Url\UrlService())->saveUrlsFromMessage($message);
1532 }
1533
1534 $allFiles = self::getFilesFromMessage(
1535 $arFields['FILE_MODELS'] ?? [],
1536 $arFields['FILES_FROM_TEXT'] ?? [],
1537 $arFields['PARAMS'] ?? []
1538 );
1539
1540 (new \Bitrix\Im\V2\Link\File\FileService())->saveFilesFromMessage($allFiles, $message);
1541 (new MessageAnalytics($message))->addSendMessage();
1542 }
1543
1545
1546 return $messageID;
1547 }
1548 else
1549 {
1550 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID");
1551 return false;
1552 }
1553
1554 }
1555 else if ($arFields['MESSAGE_TYPE'] == IM_MESSAGE_SYSTEM)
1556 {
1557 $arFields['TO_USER_ID'] = intval($arFields['TO_USER_ID']);
1558
1559 $blockedExternalAuthId = \Bitrix\Im\Model\UserTable::filterExternalUserTypes(['replica']);
1561 ->setSelect(['EXTERNAL_AUTH_ID'])
1562 ->where('ID', $arFields['TO_USER_ID'])
1563 ->where('ACTIVE', 'Y')
1564 ->fetch()
1565 ;
1566
1567 if (
1568 !$userData
1569 || in_array($userData['EXTERNAL_AUTH_ID'], $blockedExternalAuthId, true)
1570 )
1571 {
1572 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "TO_USER_ID");
1573 return false;
1574 }
1575
1576 $strSql = "
1577 SELECT ID as CHAT_ID
1578 FROM b_im_chat
1579 WHERE AUTHOR_ID = ".$arFields['TO_USER_ID']." AND TYPE = '".IM_MESSAGE_SYSTEM."'
1580 ORDER BY ID ASC
1581 ";
1582 $dbRes = $DB->Query($strSql);
1583 if ($arRes = $dbRes->Fetch())
1584 {
1585 $chatId = intval($arRes['CHAT_ID']);
1586 }
1587 else
1588 {
1590 'TYPE' => IM_MESSAGE_SYSTEM,
1591 'AUTHOR_ID' => $arFields['TO_USER_ID']
1592 ]);
1593 if (!$result->isSuccess() || !$result->hasResult())
1594 {
1595 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID");
1596 return false;
1597 }
1598
1599 $chatId = $result->getResult()['CHAT_ID'];
1600
1601 if ($chatId <= 0)
1602 {
1603 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID");
1604 return false;
1605 }
1606
1607 /*\Bitrix\Im\Model\RelationTable::add(array(
1608 "CHAT_ID" => $chatId,
1609 "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM,
1610 "USER_ID" => intval($arFields['TO_USER_ID']),
1611 //"STATUS" => ($bConvert? 2: 0),
1612 ));*/
1613 }
1614
1615 if ($chatId > 0)
1616 {
1617 $arFields['MESSAGE'] = Text::convertHtmlToBbCode($arFields['MESSAGE']);
1618 if (isset($arFields['PUSH_MESSAGE']))
1619 {
1620 $arFields['PUSH_MESSAGE'] = $html = str_replace('&nbsp;', ' ', $arFields['PUSH_MESSAGE']);;
1621 }
1622
1623 $arParams = Array();
1624 $arParams['CHAT_ID'] = $chatId;
1625 $arParams['AUTHOR_ID'] = intval($arFields['AUTHOR_ID']);
1626 $arParams['MESSAGE'] = $arFields['MESSAGE'];
1627 $arParams['MESSAGE_OUT'] = $arFields['MESSAGE_OUT'];
1628 $arParams['NOTIFY_TYPE'] = intval($arFields['NOTIFY_TYPE']);
1629 $arParams['NOTIFY_MODULE'] = $arFields['NOTIFY_MODULE'];
1630 $arParams['NOTIFY_EVENT'] = $arFields['NOTIFY_EVENT'];
1631
1632 //if (mb_strlen($arParams['MESSAGE']) <= 0 && mb_strlen($arParams['MESSAGE_OUT']) <= 0)
1633 // return false;
1634
1635 $skipAdd = false;
1636 $skipFlash = false;
1637
1638 if ($arParams['NOTIFY_TYPE'] != IM_NOTIFY_CONFIRM)
1639 {
1640 $skipAdd = !CIMSettings::GetNotifyAccess($arFields["TO_USER_ID"], $arFields["NOTIFY_MODULE"], $arFields["NOTIFY_EVENT"], CIMSettings::CLIENT_SITE);
1641 $skipFlash = $skipAdd;
1642 }
1643
1644 if (!$skipAdd && ($arFields['NOTIFY_ONLY_FLASH'] ?? null) === 'Y')
1645 {
1646 $skipAdd = true;
1647 }
1648
1649 if ($skipAdd)
1650 {
1651 $arParams['NOTIFY_READ'] = 'Y';
1652 }
1653
1654 if (isset($arFields['IMPORT_ID']))
1655 $arParams['IMPORT_ID'] = intval($arFields['IMPORT_ID']);
1656
1657 if (isset($arFields['MESSAGE_DATE']))
1658 {
1659 $arParams['DATE_CREATE'] = new Bitrix\Main\Type\DateTime($arFields['MESSAGE_DATE']);
1660 }
1661
1662 if (isset($arFields['EMAIL_TEMPLATE']) && trim($arFields['EMAIL_TEMPLATE']) <> '')
1663 $arParams['EMAIL_TEMPLATE'] = trim($arFields['EMAIL_TEMPLATE']);
1664
1665 $arParams['NOTIFY_TAG'] = isset($arFields['NOTIFY_TAG'])? $arFields['NOTIFY_TAG']: '';
1666
1667 $arParams['NOTIFY_SUB_TAG'] = isset($arFields['NOTIFY_SUB_TAG'])? $arFields['NOTIFY_SUB_TAG']: '';
1668
1669 if (isset($arFields['NOTIFY_TITLE']) && trim($arFields['NOTIFY_TITLE']) <> '')
1670 $arParams['NOTIFY_TITLE'] = trim($arFields['NOTIFY_TITLE']);
1671
1672 if ($arParams['NOTIFY_TYPE'] == IM_NOTIFY_CONFIRM)
1673 {
1674 if (isset($arFields['NOTIFY_BUTTONS']))
1675 {
1676 foreach ($arFields['NOTIFY_BUTTONS'] as $key => $arButtons)
1677 {
1678 if (is_array($arButtons))
1679 {
1680 if (isset($arButtons['TITLE']) && $arButtons['TITLE'] <> ''
1681 && isset($arButtons['VALUE']) && $arButtons['VALUE'] <> ''
1682 && isset($arButtons['TYPE']) && $arButtons['TYPE'] <> '')
1683 {
1684 $arButtons['TITLE'] = htmlspecialcharsbx($arButtons['TITLE']);
1685 $arButtons['VALUE'] = htmlspecialcharsbx($arButtons['VALUE']);
1686 $arButtons['TYPE'] = htmlspecialcharsbx($arButtons['TYPE']);
1687 $arFields['NOTIFY_BUTTONS'][$key] = $arButtons;
1688 }
1689 else
1690 unset($arFields['NOTIFY_BUTTONS'][$key]);
1691 }
1692 else
1693 unset($arFields['NOTIFY_BUTTONS'][$key]);
1694 }
1695 }
1696 else
1697 {
1698 $acceptTitleCallback = fn (?string $languageId = null) => Loc::getMessage("IM_ERROR_BUTTON_ACCEPT", null, $languageId);
1699 $cancelTitleCallback = fn (?string $languageId = null) => Loc::getMessage("IM_ERROR_BUTTON_CANCEL", null, $languageId);
1700
1701 $arFields['NOTIFY_BUTTONS'] = Array(
1702 Array(
1703 'TITLE' => CIMNotify::getTextMessageByLang($arFields['TO_USER_ID'], $acceptTitleCallback),
1704 'VALUE' => 'Y',
1705 'TYPE' => 'accept',
1706 ),
1707 Array(
1708 'TITLE' => CIMNotify::getTextMessageByLang($arFields['TO_USER_ID'], $cancelTitleCallback),
1709 'VALUE' => 'N',
1710 'TYPE' => 'cancel'
1711 ),
1712 );
1713 }
1714 $arParams['NOTIFY_BUTTONS'] = serialize($arFields["NOTIFY_BUTTONS"]);
1715 }
1716
1717 if ($skipAdd)
1718 {
1719 $messageID = time();
1720 }
1721 else
1722 {
1723 $userId = (int)$arFields['TO_USER_ID'];
1724 $relation = new Relation([
1725 'USER_ID' => (int)$arFields['TO_USER_ID'],
1726 'CHAT_ID' => $chatId,
1727 'MESSAGE_TYPE' => IM_MESSAGE_SYSTEM,
1728 'NOTIFY_BLOCK' => false,
1729 ]);
1730 $relation->setId(1);
1731
1732 $withTagNotify = isset($arParams['NOTIFY_TAG']) && $arParams['NOTIFY_TAG'] !== '';
1733 if ($withTagNotify)
1734 {
1735 $message = self::saveMessageWithTransaction($arParams, $relation, $userId);
1736 }
1737 else
1738 {
1739 $message = self::saveMessage($arParams, $relation, $userId);
1740 }
1741
1742 $messageID = $message->getMessageId();
1743 if ($messageID === null)
1744 {
1745 return false;
1746 }
1747
1748 if ($withTagNotify)
1749 {
1751 if (!$result->hasResult())
1752 {
1753 return false;
1754 }
1755
1756 $arFields['PARAMS']['USERS'] = $result->getResult();
1757 }
1758
1759 $counter = (new ReadService($userId))->getCounterService()->getByChatWithOverflow($relation->getChatId());
1760
1761 if (!empty($arFields['PARAMS']))
1762 {
1763 Notify::saveNotifyParams($messageID, $arFields['PARAMS']);
1764 }
1765
1766 \Bitrix\Im\Model\ChatTable::update($chatId, Array(
1767 'MESSAGE_COUNT' => new \Bitrix\Main\DB\SqlExpression('?# + 1', 'MESSAGE_COUNT'),
1768 'PREV_MESSAGE_ID' => new \Bitrix\Main\DB\SqlExpression('?#', 'LAST_MESSAGE_ID'),
1769 'LAST_MESSAGE_ID' => $messageID,
1770 //'LAST_MESSAGE_STATUS' => IM_MESSAGE_STATUS_RECEIVED
1771 ));
1772
1774 }
1775
1776 foreach(GetModuleEvents("im", "OnAfterNotifyAdd", true) as $arEvent)
1777 ExecuteModuleEventEx($arEvent, array(intval($messageID), $arFields));
1778
1779 if (CModule::IncludeModule('pull'))
1780 {
1781 $pullNotificationParams = CIMNotify::GetFormatNotify(
1782 [
1783 'ID' => $messageID,
1784 'DATE_CREATE' => time(),
1785 'FROM_USER_ID' => (int)$arFields['FROM_USER_ID'],
1786 'MESSAGE' => $arParams['MESSAGE'],
1787 'PARAMS' => self::PrepareParamsForPull($arFields['PARAMS']),
1788 'NOTIFY_ONLY_FLASH' => $skipAdd,
1789 'NOTIFY_LINK' => $arFields['NOTIFY_LINK'] ?? null,
1790 'NOTIFY_MODULE' => $arParams['NOTIFY_MODULE'],
1791 'NOTIFY_EVENT' => $arParams['NOTIFY_EVENT'],
1792 'NOTIFY_TAG' => $arParams['NOTIFY_TAG'],
1793 'NOTIFY_TYPE' => $arParams['NOTIFY_TYPE'],
1794 'NOTIFY_BUTTONS' => $arParams['NOTIFY_BUTTONS'] ?? serialize([]),
1795 'NOTIFY_TITLE' => $arParams['NOTIFY_TITLE'] ?? '',
1796 'COUNTER' => $counter ??= null,
1797 ]
1798 );
1799
1800 // We shouldn't send push, if it is disabled in notification settings.
1801 $needPush = CIMSettings::GetNotifyAccess(
1802 $arFields['TO_USER_ID'],
1803 $arFields['NOTIFY_MODULE'],
1804 $arFields['NOTIFY_EVENT'],
1806 );
1807
1808 if ($needPush)
1809 {
1810 // we prepare push params ONLY if there are no ADVANCED_PARAMS from outside.
1811 // If ADVANCED_PARAMS exists we must not change them.
1812 if (isset($arFields['PUSH_PARAMS']['ADVANCED_PARAMS']))
1813 {
1814 $advancedParams = $arFields['PUSH_PARAMS']['ADVANCED_PARAMS'];
1815 unset($arFields['PUSH_PARAMS']['ADVANCED_PARAMS']);
1816 }
1817 else
1818 {
1819 $advancedParams = self::prepareAdvancedParamsForNotificationPush(
1820 $pullNotificationParams,
1821 $arFields['PUSH_MESSAGE'] ?? null
1822 );
1823 }
1824
1825 \Bitrix\Pull\Push::add(
1826 $arFields['TO_USER_ID'],
1827 [
1828 'module_id' => $arParams['NOTIFY_MODULE'],
1829 'push' => [
1830 'type' => $arFields['NOTIFY_EVENT'],
1831 'message' => $arFields['PUSH_MESSAGE'] ?? null,
1832 'params' => $arFields['PUSH_PARAMS'] ?? ['TAG' => 'IM_NOTIFY'],
1833 'advanced_params' => $advancedParams,
1834 'important' => isset($arFields['PUSH_IMPORTANT']) && $arFields['PUSH_IMPORTANT'] === 'Y' ? 'Y': 'N',
1835 'tag' => $arParams['NOTIFY_TAG'],
1836 'sub_tag' => $arParams['NOTIFY_SUB_TAG'],
1837 'app_id' => $arParams['PUSH_APP_ID'] ?? '',
1838 ]
1839 ]
1840 );
1841 }
1842
1843 if (!$skipFlash)
1844 {
1846 $arFields['TO_USER_ID'],
1847 [
1848 'module_id' => 'im',
1849 'command' => 'notifyAdd',
1850 'params' => $pullNotificationParams,
1851 'extra' => \Bitrix\Im\Common::getPullExtra()
1852 ]
1853 );
1854 }
1855 }
1856
1857 if (!$skipAdd)
1858 {
1860 }
1861
1862 return $messageID;
1863 }
1864 else
1865 {
1866 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_CREATE"), "CHAT_ID");
1867 return false;
1868 }
1869 }
1870 else
1871 {
1872 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_MESSAGE_TYPE"), "MESSAGE_TYPE");
1873 return false;
1874 }
1875 }
1876
1877 private static function saveMessageWithTransaction(array $arParams, Relation $relation, int $userId): \Bitrix\Im\V2\Message
1878 {
1879 try
1880 {
1881 Application::getConnection()->startTransaction();
1882 $message = self::saveMessage($arParams, $relation, $userId);
1883 }
1884 catch (Exception $e)
1885 {
1886 Application::getConnection()->rollbackTransaction();
1887 return new \Bitrix\Im\V2\Message();
1888 }
1889
1890 Application::getConnection()->commitTransaction();
1891
1892 return $message;
1893 }
1894
1895 private static function saveMessage(array $arParams, Relation $relation, int $userId): \Bitrix\Im\V2\Message
1896 {
1897 $result = \Bitrix\Im\Model\MessageTable::add($arParams);
1898 $messageId = (int)$result->getId();
1899 $message = new \Bitrix\Im\V2\Message($arParams);
1900
1901 if ($messageId <= 0)
1902 {
1903 return $message;
1904 }
1905
1906 $message->setMessageId($messageId);
1907
1908 $relationCollection = (new RelationCollection())->add($relation);
1909 (new ReadService($userId))->markNotificationUnread($message, $relationCollection);
1910
1911 return $message;
1912 }
1913
1914 public static function IsMobileRequest()
1915 {
1916 return isset($_REQUEST['MOBILE']) && $_REQUEST['MOBILE'] == 'Y' || defined('BX_MOBILE');
1917 }
1918
1919 public static function CheckPossibilityUpdateMessage($type, $id, $userId = null)
1920 {
1921 $id = intval($id);
1922 if ($id <= 0)
1923 return false;
1924
1925 $enableCheck = self::IsEnabledMessageCheck();
1926 if ($enableCheck)
1927 {
1928 global $USER;
1929 $userId = is_null($userId)? $USER->GetId(): intval($userId);
1930 if ($userId <= 0)
1931 return false;
1932 }
1933
1934 $result = false;
1935 if (CModule::IncludeModule('pull') && CPullOptions::GetNginxStatus())
1936 {
1937 $message = self::GetById($id);
1938 $skipUserCheck = false;
1939 if ($message !== false)
1940 {
1941 $isMessageDeleted = $message['PARAMS']['IS_DELETED'] ?? null;
1942 $isForward = isset($message['PARAMS']['FORWARD_ID']);
1943 if
1944 (
1946 && (
1947 $message['AUTHOR_ID'] == 0 && $message['CHAT_ENTITY_TYPE'] === 'LINES'
1948 || !\Bitrix\Im\User::getInstance($message['AUTHOR_ID'])->isActive() && !\Bitrix\Im\User::getInstance($message['AUTHOR_ID'])->isExtranet()
1949 || \Bitrix\Im\User::getInstance($message['AUTHOR_ID'])->isConnector()
1950 || $message['CHAT_ID'] == CIMChat::GetGeneralChatId()
1951 )
1952 && self::IsAdmin()
1953 )
1954 {
1955 $skipUserCheck = true;
1956 }
1957 else if (
1959 && ($message['AUTHOR_ID'] == 0 || $isMessageDeleted === 'Y')
1960 )
1961 {}
1962 else if (
1963 $isMessageDeleted === 'Y'
1964 || ($type != IM_CHECK_DELETE && $message['DATE_CREATE'] + 259200 < time())
1965 || ($type != IM_CHECK_DELETE && $isForward)
1966 )
1967 {
1968 return false;
1969 }
1970 }
1971 else
1972 {
1973 return false;
1974 }
1975
1976 if ($enableCheck)
1977 {
1978 if ($message['CHAT_ENTITY_TYPE'] == 'LINES' && CModule::IncludeModule('imopenlines'))
1979 {
1980 [$connectorType] = explode("|", $message['CHAT_ENTITY_ID']);
1981 if (\Bitrix\Im\User::getInstance($userId)->isBot())
1982 {
1983 if ($message['AUTHOR_ID'] != $userId)
1984 {
1985 $relation = \CIMMessenger::GetRelationById($id);
1986 if (!isset($relation[$userId]))
1987 {
1988 return false;
1989 }
1990 }
1991 }
1992 else if ($message['AUTHOR_ID'] == $userId)
1993 {
1994 if (!($type == IM_CHECK_UPDATE && in_array($connectorType, \Bitrix\ImOpenlines\Connector::getListCanUpdateOwnMessage()))
1995 && !($type == IM_CHECK_DELETE && in_array($connectorType, \Bitrix\ImOpenlines\Connector::getListCanDeleteOwnMessage())))
1996 {
1997 return false;
1998 }
1999 }
2000 else
2001 {
2002 if ($type == IM_CHECK_UPDATE || !$skipUserCheck && !in_array($connectorType, \Bitrix\ImOpenlines\Connector::getListCanDeleteMessage()))
2003 {
2004 return false;
2005 }
2006 }
2007 }
2008 else if (!$skipUserCheck && $message['AUTHOR_ID'] != $userId)
2009 {
2010 return false;
2011 }
2012 }
2013
2014 $result = $message;
2015 }
2016
2017 return $result;
2018 }
2019
2020 public static function Update($id, $text, $urlPreview = true, $editFlag = true, $userId = null, $byEvent = false, $convert = false)
2021 {
2022 if (mb_strlen($text) > self::MESSAGE_LIMIT + 6)
2023 {
2024 $text = mb_substr($text, 0, self::MESSAGE_LIMIT).' (...)';
2025 }
2026
2027 $updateFlags = Array(
2028 'ID' => $id,
2029 'TEXT' => $text,
2030 'URL_PREVIEW' => $urlPreview,
2031 'EDIT_FLAG' => $editFlag,
2032 'USER_ID' => $userId,
2033 'BY_EVENT' => $byEvent,
2034 );
2035
2036 $text = trim(str_replace(Array('[BR]', '[br]'), "\n", $text));
2037 if ($text == '')
2038 {
2039 return self::Delete($id, $userId, false, $byEvent);
2040 }
2041
2042 $message =
2043 !$convert
2044 ? self::CheckPossibilityUpdateMessage(IM_CHECK_UPDATE, $id, $userId)
2045 : self::GetById((int)$id)
2046 ;
2047 if (!$message)
2048 return false;
2049
2050
2051 $dateText = Array();
2052 $dateTs = Array();
2053
2054 if ($urlPreview)
2055 {
2057 foreach ($results as $result)
2058 {
2059 $dateText[] = $result->getText();
2060 $dateTs[] = $result->getDate()->getTimestamp();
2061 }
2062 }
2063
2064 $arUpdate = Array('MESSAGE' => $text, 'MESSAGE_OUT' => '');
2065 $urlId = Array();
2066 $urlOnly = false;
2067 if ($urlPreview)
2068 {
2069 $link = new CIMMessageLink();
2070 $urlPrepare = $link->prepareInsert($text);
2071 if ($urlPrepare['RESULT'])
2072 {
2073 $arUpdate['MESSAGE_OUT'] = $text;
2074 $arUpdate['MESSAGE'] = $urlPrepare['MESSAGE'];
2075 $urlId = $urlPrepare['URL_ID'];
2076 if ($urlPrepare['MESSAGE_IS_LINK'])
2077 {
2078 $urlOnly = true;
2079 }
2080 }
2081 }
2082
2083 $isOnlyEmoji = Text::isOnlyEmoji($arUpdate['MESSAGE']);
2084 $newParams = [
2085 'IS_EDITED' => $editFlag ?'Y' : 'N',
2086 'URL_ID' => $urlId,
2087 'URL_ONLY' => $urlOnly ? 'Y' : 'N',
2088 'LARGE_FONT' => $isOnlyEmoji ? 'Y' : 'N',
2089 'DATE_TEXT' => $dateText,
2090 'DATE_TS' => $dateTs,
2091 ];
2092
2093 $uploadResult = self::UploadFileFromText(['MESSAGE' => $arUpdate['MESSAGE'], 'CHAT_ID' => (int)$message['CHAT_ID']]);
2094 $arUpdate['MESSAGE'] = $uploadResult['MESSAGE'];
2095 $fileIds = [];
2096 if (!empty($uploadResult['PARAMS']['FILE_ID']))
2097 {
2098 $newParams['FILE_ID'] = array_merge($message['PARAMS']['FILE_ID'] ?? [], $uploadResult['PARAMS']['FILE_ID'] ?? []);
2099 }
2100
2101 \Bitrix\Im\Model\MessageTable::update($message['ID'], $arUpdate);
2102 CIMMessageParam::Set($message['ID'], $newParams);
2103
2104 if (!$convert)
2105 {
2107 $arFields['MESSAGE'] = $arUpdate['MESSAGE'];
2108 $arFields['DATE_MODIFY'] = new \Bitrix\Main\Type\DateTime();
2109
2110 $pullMessage = Text::parse($arFields['MESSAGE']);
2111
2112 $relations = CIMMessenger::GetRelationById($message['ID']);
2113
2114 $arPullMessage = Array(
2115 'id' => (int)$arFields['ID'],
2116 'type' => $arFields['MESSAGE_TYPE'] == IM_MESSAGE_PRIVATE? 'private': 'chat',
2117 'text' => $pullMessage,
2118 'textLegacy' => Text::parseLegacyFormat($arFields['MESSAGE']),
2119 );
2120 $arBotInChat = Array();
2121
2122 if ($message['MESSAGE_TYPE'] == IM_MESSAGE_PRIVATE)
2123 {
2124 $arFields['FROM_USER_ID'] = $arFields['AUTHOR_ID'];
2125 $arFields['TO_USER_ID'] = $arFields['AUTHOR_ID'];
2126 foreach ($relations as $rel)
2127 {
2128 if ($rel['USER_ID'] != $arFields['AUTHOR_ID'])
2129 {
2130 $arFields['TO_USER_ID'] = $rel['USER_ID'];
2131 }
2132 }
2133
2134 $arPullMessage['fromUserId'] = (int)$arFields['FROM_USER_ID'];
2135 $arPullMessage['toUserId'] = (int)$arFields['TO_USER_ID'];
2136 $arPullMessage['senderId'] = (int)$arFields['FROM_USER_ID'];
2137 $arPullMessage['chatId'] = (int)$arFields['CHAT_ID'];
2138 }
2139 else
2140 {
2141 $arPullMessage['chatId'] = (int)$arFields['CHAT_ID'];
2142 $arPullMessage['senderId'] = (int)$arFields['AUTHOR_ID'];
2143
2144 foreach ($relations as $relation)
2145 {
2146 if ($message['CHAT_ENTITY_TYPE'] == 'LINES')
2147 {
2148 if ($relation["EXTERNAL_AUTH_ID"] == 'imconnector')
2149 {
2150 unset($relations[$relation["USER_ID"]]);
2151 continue;
2152 }
2153 }
2154 if ($relation["EXTERNAL_AUTH_ID"] == \Bitrix\Im\Bot::EXTERNAL_AUTH_ID)
2155 {
2156 $arBotInChat[$relation["USER_ID"]] = $relation["USER_ID"];
2157 unset($relations[$relation["USER_ID"]]);
2158 continue;
2159 }
2160 }
2161 }
2162
2163 $arMessages[$message['ID']] = [];
2164
2165 $params = CIMMessageParam::Get([$message['ID']], false);
2166 $arMessages[$message['ID']]['params'] = $params[$message['ID']];
2167
2168 $arDefault = CIMMessageParam::GetDefault();
2169 if (!isset($arMessages[$message['ID']]['params']['IS_EDITED']))
2170 {
2171 $arMessages[$message['ID']]['params']['IS_EDITED'] = $arDefault['IS_EDITED'];
2172 }
2173 if (!isset($arMessages[$message['ID']]['params']['URL_ID']))
2174 {
2175 $arMessages[$message['ID']]['params']['URL_ID'] = $arDefault['URL_ID'];
2176 }
2177 if (!isset($arMessages[$message['ID']]['params']['ATTACH']))
2178 {
2179 $arMessages[$message['ID']]['params']['ATTACH'] = $arDefault['ATTACH'];
2180 }
2181 if (!isset($arMessages[$message['ID']]['params']['DATE_TEXT']))
2182 {
2183 $arMessages[$message['ID']]['params']['DATE_TEXT'] = $arDefault['DATE_TEXT'];
2184 }
2185 if (!isset($arMessages[$message['ID']]['params']['DATE_TS']))
2186 {
2187 $arMessages[$message['ID']]['params']['DATE_TS'] = $arDefault['DATE_TS'];
2188 }
2189
2190 $arMessages = CIMMessageLink::prepareShow($arMessages, $params);
2191 $arPullMessage['params'] = CIMMessenger::PrepareParamsForPull($arMessages[$message['ID']]['params']);
2192
2193 $pull = [];
2194 if ($message['MESSAGE_TYPE'] == IM_MESSAGE_PRIVATE)
2195 {
2196 $arPullMessage['dialogId'] = (int)$arFields['FROM_USER_ID'];
2197 $arPullMessage['fromUserId'] = (int)$arFields['FROM_USER_ID'];
2198 $arPullMessage['toUserId'] = (int)$arFields['TO_USER_ID'];
2199
2200 \Bitrix\Pull\Event::add($arPullMessage['toUserId'], [
2201 'module_id' => 'im',
2202 'command' => 'messageUpdate',
2203 'params' => $arPullMessage,
2204 'extra' => \Bitrix\Im\Common::getPullExtra()
2205 ]);
2206
2207 $arPullMessage['dialogId'] = (int)$arFields['TO_USER_ID'];
2208 $arPullMessage['fromUserId'] = (int)$arFields['TO_USER_ID'];
2209 $arPullMessage['toUserId'] = (int)$arFields['FROM_USER_ID'];
2210
2211 \Bitrix\Pull\Event::add($arPullMessage['toUserId'], [
2212 'module_id' => 'im',
2213 'command' => 'messageUpdate',
2214 'params' => $arPullMessage,
2215 'extra' => \Bitrix\Im\Common::getPullExtra()
2216 ]);
2217 }
2218 else
2219 {
2220 $arPullMessage['dialogId'] = 'chat' . $arPullMessage['chatId'];
2221 $pull = [
2222 'module_id' => 'im',
2223 'command' => 'messageUpdate',
2224 'params' => $arPullMessage,
2226 ];
2227
2228 if ($message['MESSAGE_TYPE'] === Chat::IM_TYPE_COMMENT)
2229 {
2230 CPullWatch::AddToStack('IM_PUBLIC_COMMENT_' . $message['CHAT_PARENT_ID'], $pull);
2231 }
2232 else
2233 {
2234 \Bitrix\Pull\Event::add(array_keys($relations), $pull);
2235 }
2236 }
2237
2238 if (self::needToSendPublicPull($message['MESSAGE_TYPE']))
2239 {
2240 CPullWatch::AddToStack('IM_PUBLIC_' . $message['CHAT_ID'], $pull);
2241 }
2242 if ($message['MESSAGE_TYPE'] === Chat::IM_TYPE_OPEN_CHANNEL && (int)$id === (int)$message['CHAT_LAST_MESSAGE_ID'])
2243 {
2245 }
2246 if ($message['MESSAGE_TYPE'] != IM_MESSAGE_PRIVATE)
2247 {
2248 $arFields['BOT_IN_CHAT'] = $arBotInChat;
2249 }
2250
2252 "UPDATE b_im_recent SET DATE_UPDATE = NOW() WHERE ITEM_MID = " . intval($id)
2253 );
2254
2255 foreach (GetModuleEvents("im", "OnAfterMessagesUpdate", true) as $arEvent)
2256 {
2257 ExecuteModuleEventEx($arEvent, [intval($id), $arFields, $updateFlags]);
2258 }
2259
2260 \Bitrix\Im\Bot::onMessageUpdate(intval($id), $arFields);
2261
2262 $message = (new \Bitrix\Im\V2\Message())
2263 ->setMessageId((int)$id)
2264 ->setMessage($arFields['MESSAGE'])
2265 ->setChatId((int)$arFields['CHAT_ID'])
2266 ->setAuthorId((int)$arFields['AUTHOR_ID'])
2267 ;
2268 $chat = Chat::getInstance((int)$arFields['CHAT_ID']);
2271 array_keys($relations),
2272 $chat
2273 );
2274 (new \Bitrix\Im\V2\Link\Url\UrlService())->updateUrlsFromMessage($message);
2275 (new \Bitrix\Im\V2\Link\File\FileService())->saveFilesFromMessage($uploadResult['FILES_FROM_TEXT'] ?? [], $message);
2276 }
2277
2279
2280 return true;
2281 }
2282
2283 public static function Share($id, $type, $date = '')
2284 {
2285 $chat = new CIMShare();
2286
2287 if (\Bitrix\Im\User::getInstance($chat->user_id)->isExtranet())
2288 {
2289 return false;
2290 }
2291
2292 if ($type == 'CHAT')
2293 {
2294 $result = $chat->Chat($id);
2295 }
2296 else if ($type == 'TASK')
2297 {
2298 $result = $chat->Task($id, $date);
2299 }
2300 else if ($type == 'POST')
2301 {
2302 $result = $chat->Post($id);
2303 }
2304 else if ($type == 'CALEND')
2305 {
2306 $result = $chat->Calendar($id, $date);
2307 }
2308
2309 return $result;
2310 }
2311
2319 public static function disappearMessage(int $messageId, int $hours, ?int $userId = null): bool
2320 {
2321 if (!self::CheckPossibilityUpdateMessage(IM_CHECK_DELETE, $messageId, $userId))
2322 {
2323 return false;
2324 }
2325
2326 $message = new \Bitrix\Im\V2\Message($messageId);
2327 if (!$message->getMessageId())
2328 {
2329 return false;
2330 }
2331
2333 return $result->isSuccess();
2334 }
2335
2336 public static function Delete($id, $userId = null, $completeDelete = false, $byEvent = false)
2337 {
2338 $message = self::CheckPossibilityUpdateMessage(IM_CHECK_DELETE, $id, $userId);
2339 if (!$message)
2340 return false;
2341
2342 $completeDelete = $message['CHAT_ID'] == CIMChat::GetGeneralChatId() && self::IsAdmin()? true: $completeDelete;
2343
2345 $messageObject = new \Bitrix\Im\V2\Message((int)$id);
2346 if (!$messageObject->getId())
2347 {
2348 return false;
2349 }
2350
2352 $deleteService->setContext((new \Bitrix\Im\V2\Service\Context())->setUserId($userId));
2353 $deleteService->setByEvent($byEvent);
2354 if ($completeDelete)
2355 {
2356 $deleteService->setMode(\Bitrix\Im\V2\Message\Delete\DeletionMode::Complete);
2357 }
2358 else
2359 {
2360 $deleteService->setMode(\Bitrix\Im\V2\Message\Delete\DeletionMode::Soft);
2361 }
2362
2363 $deleteService->delete();
2364
2365 return true;
2366 }
2367
2368 public static function LinesSessionVote($dialogId, $messageId, $action, $userId = null)
2369 {
2370 global $USER;
2371 $userId = is_null($userId) ? $USER->getId(): (int)$userId;
2372 $messageId = (int)$messageId;
2373
2374 if ($userId <= 0 || $messageId <= 0 || $dialogId == '')
2375 {
2376 return false;
2377 }
2378
2379 $message = self::getById($messageId);
2380 if (!$message)
2381 {
2382 return false;
2383 }
2384
2385 // only messages from network bots
2386 if (!\Bitrix\Im\User::getInstance($message['AUTHOR_ID'])->isBot() || !\Bitrix\Im\User::getInstance($message['AUTHOR_ID'])->isNetwork())
2387 {
2388 return false;
2389 }
2390
2391 $sessionId = (int)$message['PARAMS']['IMOL_VOTE_SID'];
2392 if ($sessionId <= 0)
2393 {
2394 return false;
2395 }
2396
2397 $timeToVote = (int)$message['PARAMS']['IMOL_TIME_LIMIT_VOTE'];
2398 if ($timeToVote > 0 && ($message['DATE_CREATE'] + $timeToVote < time()))
2399 {
2400 // expired
2401 return false;
2402 }
2403
2404 $relations = self::getRelationById($messageId);
2405 if (!isset($relations[$userId]))
2406 {
2407 return false;
2408 }
2409
2410 $action = $action == 'dislike' ? 'dislike': 'like';
2411
2412 $compParams = $message['PARAMS']['COMPONENT_PARAMS'] ?? [];
2413 $compParams['IMOL_VOTE'] = $action;
2414
2415 \CIMMessageParam::set($messageId, ['IMOL_VOTE' => $action, 'COMPONENT_PARAMS' => $compParams]);
2416 \CIMMessageParam::sendPull($messageId, ['IMOL_VOTE', 'COMPONENT_PARAMS']);
2417
2418 $chat = \Bitrix\Im\Model\ChatTable::getByPrimary($message['CHAT_ID'])->fetch();
2419 if ($chat['ENTITY_TYPE'] == 'LIVECHAT')
2420 {
2421 \CIMMessageParam::set($message['PARAMS']['CONNECTOR_MID'][0], Array('IMOL_VOTE' => $action));
2422 \CIMMessageParam::sendPull($message['PARAMS']['CONNECTOR_MID'][0], Array('IMOL_VOTE'));
2423
2424 if (\Bitrix\Main\Loader::includeModule('imopenlines'))
2425 {
2426 \Bitrix\ImOpenlines\Session::voteAsUser($sessionId, $action);
2427 }
2428 }
2429
2430 foreach(\GetModuleEvents('im', 'OnSessionVote', true) as $arEvent)
2431 {
2433 'DIALOG_ID' => $dialogId,
2434 'MESSAGE_ID' => $messageId,
2435 'SESSION_ID' => $sessionId,
2436 'MESSAGE' => $message,
2437 'ACTION' => $action,
2438 'CHAT' => $chat,
2439 'RELATION' => $relations,
2440 'USER_ID' => $userId
2441 )));
2442 }
2443
2444 return true;
2445 }
2446
2447 public static function Like($id, $action = 'auto', $userId = null, $byEvent = false, $withReaction = true)
2448 {
2449 if (!CModule::IncludeModule('pull'))
2450 return false;
2451
2452 global $USER;
2453 $userId = is_null($userId)? $USER->GetId(): intval($userId);
2454 if ($userId <= 0)
2455 return false;
2456
2457 $action = in_array($action, Array('plus', 'minus'))? $action: 'auto';
2458
2459 $message = self::GetById($id);
2460 if (!$message)
2461 return false;
2462
2463 $relations = self::GetRelationById($id);
2464
2465 $result = \Bitrix\Im\Model\ChatTable::getList(Array(
2466 'filter'=>Array(
2467 '=ID' => $message['CHAT_ID']
2468 )
2469 ));
2470 $chat = $result->fetch();
2471 if ($chat['ENTITY_TYPE'] != 'LIVECHAT')
2472 {
2473 if (!isset($relations[$userId]))
2474 return false;
2475 }
2476
2477 if (!$byEvent && $chat['ENTITY_TYPE'] == 'LINES')
2478 {
2479 [$connectorType, $lineId, $chatId] = explode("|", $chat['ENTITY_ID']);
2480 if ($connectorType == "livechat")
2481 {
2482 foreach($message['PARAMS']['CONNECTOR_MID'] as $mid)
2483 {
2484 self::Like($mid, $action, $userId, true, false);
2485 }
2486 }
2487 }
2488 else if (!$byEvent && $chat['ENTITY_TYPE'] == 'LIVECHAT')
2489 {
2490 foreach($message['PARAMS']['CONNECTOR_MID'] as $mid)
2491 {
2492 self::Like($mid, $action, $userId, true, false);
2493 }
2494 }
2495
2496 $isLike = false;
2497 if (isset($message['PARAMS']['LIKE']))
2498 {
2499 $isLike = in_array($userId, $message['PARAMS']['LIKE']);
2500 }
2501
2502 if ($isLike && $action == 'plus')
2503 {
2504 return false;
2505 }
2506 else if (!$isLike && $action == 'minus')
2507 {
2508 return false;
2509 }
2510
2511 $isLike = true;
2512 if (isset($message['PARAMS']['LIKE']))
2513 {
2514 $like = $message['PARAMS']['LIKE'];
2515 $selfLike = array_search($userId, $like);
2516 if ($selfLike !== false)
2517 {
2518 $isLike = false;
2519 unset($like[$selfLike]);
2520 }
2521 else
2522 {
2523 $like[] = $userId;
2524 }
2525 }
2526 else
2527 {
2528 $like = Array($userId);
2529 }
2530
2531 sort($like);
2532 CIMMessageParam::Set($id, Array('LIKE' => $like));
2533
2534 if ($withReaction)
2535 {
2536 $messageObject = new \Bitrix\Im\V2\Message([
2537 'ID' => $message['ID'],
2538 'CHAT_ID' => $message['CHAT_ID'],
2539 'AUTHOR_ID' => $message['AUTHOR_ID'],
2540 'MESSAGE' => $message['MESSAGE'],
2541 ]);
2542 $reactionService = new \Bitrix\Im\V2\Message\Reaction\ReactionService($messageObject, false);
2543
2544 if ($isLike)
2545 {
2546 $reactionService->addReaction(\Bitrix\Im\V2\Message\Reaction\ReactionItem::LIKE);
2547 }
2548 else
2549 {
2550 $reactionService->deleteReaction(\Bitrix\Im\V2\Message\Reaction\ReactionItem::LIKE);
2551 }
2552 }
2553
2554 if ($message['AUTHOR_ID'] > 0 && $message['AUTHOR_ID'] != $userId && $isLike && $chat['ENTITY_TYPE'] != 'LIVECHAT')
2555 {
2556 $message['MESSAGE'] = self::PrepareParamsForPush($message);
2557
2558 $isChat = $chat && $chat['TITLE'] <> '';
2559
2560 $dot = mb_strlen($message['MESSAGE']) >= 200? '...': '';
2561 $message['MESSAGE'] = mb_substr($message['MESSAGE'], 0, 199).$dot;
2562 $message['MESSAGE'] = $message['MESSAGE'] <> ''? $message['MESSAGE']: '-';
2563
2564 /*$arMessageFields = array(
2565 "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM,
2566 "TO_USER_ID" => $message['AUTHOR_ID'],
2567 "FROM_USER_ID" => $userId,
2568 "NOTIFY_TYPE" => IM_NOTIFY_FROM,
2569 "NOTIFY_MODULE" => "im",
2570 "NOTIFY_EVENT" => "like",
2571 "NOTIFY_TAG" => "RATING|IM|".($isChat? 'G':'P')."|".($isChat? $chat['ID']: $userId)."|".$id,
2572 "NOTIFY_MESSAGE" => GetMessage($isChat? 'IM_MESSAGE_LIKE': 'IM_MESSAGE_LIKE_PRIVATE', Array(
2573 '#MESSAGE#' => $message['MESSAGE'],
2574 '#TITLE#' => $isChat? '[CHAT='.$chat['ID'].']'.$chat['TITLE'].'[/CHAT]': $chat['TITLE']
2575 )),
2576 "NOTIFY_MESSAGE_OUT" => GetMessage($isChat? 'IM_MESSAGE_LIKE': 'IM_MESSAGE_LIKE_PRIVATE', Array(
2577 '#MESSAGE#' => $message['MESSAGE'],
2578 '#TITLE#' => $chat['TITLE']
2579 )),
2580 );
2581 CIMNotify::Add($arMessageFields);*/
2582 }
2583
2584 $pushUsers = $like;
2585 $pushUsers[] = $message['AUTHOR_ID'];
2586
2587 $arPullMessage = Array(
2588 'id' => (int)$id,
2589 'dialogId' => 0,
2590 'chatId' => (int)$chat['ID'],
2591 'senderId' => (int)$userId,
2592 'set' => (bool)$isLike,
2593 'users' => $like
2594 );
2595
2596 if ($chat['TYPE'] == IM_MESSAGE_PRIVATE)
2597 {
2598 $fromUserId = (int)$userId;
2599 foreach ($relations as $rel)
2600 {
2601 if ($rel['USER_ID'] != $fromUserId)
2602 {
2603 $toUserId = (int)$rel['USER_ID'];
2604 }
2605 }
2606 $dialogId = $toUserId;
2607
2608 \Bitrix\Pull\Event::add($fromUserId, Array(
2609 'module_id' => 'im',
2610 'command' => 'messageLike',
2611 'params' => array_merge($arPullMessage, ['dialogId' => $toUserId]),
2612 'extra' => \Bitrix\Im\Common::getPullExtra()
2613 ));
2614
2615 \Bitrix\Pull\Event::add($toUserId, Array(
2616 'module_id' => 'im',
2617 'command' => 'messageLike',
2618 'params' => array_merge($arPullMessage, ['dialogId' => $fromUserId]),
2619 'extra' => \Bitrix\Im\Common::getPullExtra()
2620 ));
2621 }
2622 else
2623 {
2624 $dialogId = 'chat'.$chat['ID'];
2625 $arPullMessage['dialogId'] = $dialogId;
2626
2627 if ($chat['ENTITY_TYPE'] == 'LINES')
2628 {
2629 foreach ($relations as $rel)
2630 {
2631 if ($rel["EXTERNAL_AUTH_ID"] == 'imconnector')
2632 {
2633 unset($relations[$rel["USER_ID"]]);
2634 }
2635 }
2636 }
2637 $pull = [
2638 'module_id' => 'im',
2639 'command' => 'messageLike',
2640 'params' => $arPullMessage,
2642 ];
2643
2644 if ($chat['TYPE'] === Chat::IM_TYPE_COMMENT)
2645 {
2646 CPullWatch::AddToStack('IM_PUBLIC_COMMENT_'.$chat['PARENT_ID'], $pull);
2647 }
2648 else
2649 {
2650 \Bitrix\Pull\Event::add(array_keys($relations), $pull);
2651 }
2652
2653 if (self::needToSendPublicPull($chat['TYPE']))
2654 {
2655 CPullWatch::AddToStack('IM_PUBLIC_'.$chat['ID'], $pull);
2656 }
2657 }
2658
2659 foreach(GetModuleEvents("im", "OnAfterMessagesLike", true) as $arEvent)
2660 {
2662 'DIALOG_ID' => $dialogId,
2663 'CHAT' => $chat,
2664 'MESSAGE' => $message,
2665 'ACTION' => $action,
2666 'USER_ID' => $userId,
2667 'BY_EVENT' => $byEvent
2668 )));
2669 }
2670
2671 return $like;
2672 }
2673
2674 public static function ExecCommand($id, $botId, $command, $commandParams = '', $userId = null, $byEvent = false)
2675 {
2676 global $USER;
2677 $userId = is_null($userId)? $USER->GetId(): intval($userId);
2678 if ($userId <= 0)
2679 return false;
2680
2681 $messageId = intval($id);
2682
2683 $orm = \Bitrix\Im\Model\MessageTable::getById($messageId);
2684 $message = $orm->fetch();
2685
2686 if(!$message)
2687 {
2688 return false;
2689 }
2690
2691 $orm = \Bitrix\Im\Model\ChatTable::getById($message['CHAT_ID']);
2692 $chat = $orm->fetch();
2693 if (!$chat)
2694 {
2695 return false;
2696 }
2697
2698 $relations = \CIMChat::GetRelationById($message['CHAT_ID'], false, true, false);
2699 if (!isset($relations[$userId]))
2700 {
2701 return false;
2702 }
2703
2704 $entityType = $chat['ENTITY_TYPE'];
2705 $entityId = $chat['ENTITY_ID'];
2706
2707 if ($chat['TYPE'] != IM_MESSAGE_PRIVATE)
2708 {
2709 $chatId = $message['CHAT_ID'];
2710 $messageType = $chat['TYPE'];
2711
2712 if ($chat['ENTITY_TYPE'] === 'LIVECHAT') // TODO finalize it
2713 {
2714 [$lineId, $userId] = explode("|", $chat['ENTITY_ID']);
2715
2716 $entityType = 'LINES';
2717 $entityId = 'livechat|'.$lineId.'|'.$message['CHAT_ID'].'|'.$userId;
2718
2719 $chatLines = \Bitrix\Im\Model\ChatTable::getList(Array(
2720 'select' => ['ID'],
2721 'filter' => [
2722 '=ENTITY_TYPE' => $entityType,
2723 '=ENTITY_ID' => $entityId,
2724 ]
2725 ))->fetch();
2726 if (!$chatLines)
2727 {
2728 return false;
2729 }
2730
2731 $chatId = $chatLines['ID'];
2732 $messageType = $chatLines['TYPE'];
2733 }
2734
2735 $messageFields = Array(
2736 "FROM_USER_ID" => $userId,
2737 "TO_CHAT_ID" => $chatId,
2738 "MESSAGE" => '/'.$command.' '.$commandParams,
2739 );
2740 }
2741 else
2742 {
2743 $messageFields = Array(
2744 "FROM_USER_ID" => $userId,
2745 "TO_USER_ID" => intval($botId),
2746 "MESSAGE" => '/'.$_POST['COMMAND'].' '.$_POST['COMMAND_PARAMS'],
2747 );
2748
2749 $messageType = $relations[$userId]['MESSAGE_TYPE'];
2750 }
2751
2752 $messageFields['MESSAGE_TYPE'] = $messageType;
2753 $messageFields['CHAT_ENTITY_TYPE'] = $entityType;
2754 $messageFields['CHAT_ENTITY_ID'] = $entityId;
2755 $messageFields['AUTHOR_ID'] = $userId;
2756 $messageFields['COMMAND_CONTEXT'] = 'KEYBOARD';
2757
2759
2760 return true;
2761 }
2762
2763 public static function UrlAttachDelete($id, $attachId = false, $userId = null)
2764 {
2765 if (!CModule::IncludeModule('pull'))
2766 return false;
2767
2768 global $USER;
2769 $userId = is_null($userId)? $USER->GetId(): intval($userId);
2770 if ($userId <= 0)
2771 return false;
2772
2773 $relations = CIMMessenger::GetRelationById($id);
2774 if (!isset($relations[$userId]))
2775 return false;
2776
2777 $newUrlId = Array();
2778 if ($attachId)
2779 {
2780 $urlId = CIMMessageParam::Get($id, 'URL_ID');
2781 foreach ($urlId as $value)
2782 {
2783 if ($value != $attachId)
2784 {
2785 $newUrlId[] = $value;
2786 }
2787 }
2788 }
2789
2790 CIMMessageParam::Set($id, Array('URL_ID' => $newUrlId, 'URL_ONLY' => empty($newUrlId)? 'N': 'Y'));
2791 CIMMessageParam::SendPull($id, Array('URL_ID', 'ATTACH', 'URL_ONLY'));
2792
2793 return true;
2794 }
2795
2796 private static function CheckFields($arFields)
2797 {
2798 $messageType = $arFields['MESSAGE_TYPE'] ?? null;
2799 $messageDate = $arFields['MESSAGE_DATE'] ?? null;
2800 $message = $arFields['MESSAGE'] ?? null;
2801 $system = $arFields['SYSTEM'] ?? null;
2802 $importId = $arFields['IMPORT_ID'] ?? null;
2803 $authorId = $arFields['AUTHOR_ID'] ?? null;
2804 $toChatId = $arFields['TO_CHAT_ID'] ?? null;
2805 $toUserId = $arFields['TO_USER_ID'] ?? null;
2806 $fromUserId = $arFields['FROM_USER_ID'] ?? null;
2807
2808 $aMsg = array();
2809 if (
2810 !$messageType
2811 || !in_array($messageType, Chat::IM_TYPES, true)
2812 )
2813 {
2814 $aMsg[] = array("id"=>"MESSAGE_TYPE", "text"=> GetMessage("IM_ERROR_MESSAGE_TYPE"));
2815 }
2816 else
2817 {
2818 if (
2819 in_array($messageType, CIMChat::getGroupTypesExtra(), true)
2820 && !$system
2821 && (int)$toChatId <= 0
2822 && (int)$fromUserId <= 0
2823 )
2824 {
2825 $aMsg[] = array("id"=>"TO_CHAT_ID", "text"=> GetMessage("IM_ERROR_MESSAGE_TO_FROM"));
2826 }
2827
2828 if (
2829 $messageType === IM_MESSAGE_PRIVATE
2830 && !(
2831 ((int)$toUserId > 0 || (int)$toChatId > 0) && (int)$fromUserId > 0
2832 )
2833 )
2834 {
2835 $aMsg[] = array("id"=>"FROM_USER_ID", "text"=> GetMessage("IM_ERROR_MESSAGE_TO_FROM"));
2836 }
2837
2838 if ($messageDate && (!$GLOBALS['DB']->IsDate($messageDate, false, LANG, "FULL")))
2839 {
2840 $aMsg[] = array("id"=>"MESSAGE_DATE", "text"=> GetMessage("IM_ERROR_MESSAGE_DATE"));
2841 }
2842
2843 if (
2844 in_array($messageType, [IM_MESSAGE_PRIVATE, IM_MESSAGE_SYSTEM], true)
2845 && !((int)$toUserId > 0 || (int)$toChatId > 0)
2846 )
2847 {
2848 $aMsg[] = array("id"=>"TO_USER_ID", "text"=> GetMessage("IM_ERROR_MESSAGE_TO"));
2849 }
2850
2851 if (!is_null($message) && trim($message) == '')
2852 {
2853 $aMsg[] = array("id"=>"MESSAGE", "text"=> GetMessage("IM_ERROR_MESSAGE_TEXT"));
2854 }
2855 else if(is_null($message) && $messageType === IM_MESSAGE_SYSTEM && empty($arFields['PARAMS']['ATTACH']))
2856 {
2857 $aMsg[] = array("id"=>"MESSAGE", "text"=> GetMessage("IM_ERROR_MESSAGE_TEXT"));
2858 }
2859 else if(is_null($message) && empty($arFields['PARAMS']['ATTACH']) && empty($arFields['PARAMS']['FILE_ID']))
2860 {
2861 $aMsg[] = array("id"=>"MESSAGE", "text"=> GetMessage("IM_ERROR_MESSAGE_TEXT"));
2862 }
2863
2864 if ($messageType === IM_MESSAGE_PRIVATE && $authorId && (int)$authorId <= 0)
2865 {
2866 $aMsg[] = ["id" => "AUTHOR_ID", "text" => GetMessage("IM_ERROR_MESSAGE_AUTHOR")];
2867 }
2868
2869 if ($importId && (int)$importId <= 0)
2870 {
2871 $aMsg[] = ["id" => "IMPORT_ID", "text" => GetMessage("IM_ERROR_IMPORT_ID")];
2872 }
2873
2874 if ($messageType === IM_MESSAGE_SYSTEM)
2875 {
2876 if (isset($arFields["NOTIFY_MODULE"]) && trim($arFields["NOTIFY_MODULE"]) == '')
2877 {
2878 $aMsg[] = ["id" => "NOTIFY_MODULE", "text" => GetMessage("IM_ERROR_NOTIFY_MODULE")];
2879 }
2880
2881 if (isset($arFields["NOTIFY_EVENT"]) && trim($arFields["NOTIFY_EVENT"]) == '')
2882 {
2883 $aMsg[] = ["id" => "NOTIFY_EVENT", "text" => GetMessage("IM_ERROR_NOTIFY_EVENT")];
2884 }
2885
2886 if (isset($arFields["NOTIFY_TYPE"]) && !in_array($arFields["NOTIFY_TYPE"], [IM_NOTIFY_CONFIRM, IM_NOTIFY_SYSTEM, IM_NOTIFY_FROM], true))
2887 {
2888 $aMsg[] = ["id" => "NOTIFY_TYPE", "text" => GetMessage("IM_ERROR_NOTIFY_TYPE")];
2889 }
2890
2891 if (isset($arFields["NOTIFY_TYPE"]) && $arFields["NOTIFY_TYPE"] == IM_NOTIFY_CONFIRM)
2892 {
2893 if(isset($arFields["NOTIFY_BUTTONS"]) && !is_array($arFields["NOTIFY_BUTTONS"]))
2894 {
2895 $aMsg[] = ["id" => "NOTIFY_BUTTONS", "text" => GetMessage("IM_ERROR_NOTIFY_BUTTON")];
2896 }
2897 }
2898 else if(isset($arFields["NOTIFY_TYPE"]) && $arFields["NOTIFY_TYPE"] == IM_NOTIFY_FROM)
2899 {
2900 if (!$fromUserId || (int)$fromUserId <= 0)
2901 {
2902 $aMsg[] = ["id" => "FROM_USER_ID", "text" => GetMessage("IM_ERROR_MESSAGE_FROM")];
2903 }
2904 }
2905 }
2906 }
2907
2908 if(!empty($aMsg))
2909 {
2910 $e = new CAdminException($aMsg);
2911 $GLOBALS["APPLICATION"]->ThrowException($e);
2912 return false;
2913 }
2914
2915 return true;
2916 }
2917
2918 public static function GetById($ID, $params = Array())
2919 {
2920 global $DB;
2921
2922 $ID = intval($ID);
2923
2924 $strSql = "
2925 SELECT DISTINCT
2926 M.*,
2927 ".$DB->DatetimeToTimestampFunction('M.DATE_CREATE')." as DATE_CREATE,
2928 C.TYPE as MESSAGE_TYPE,
2929 C.AUTHOR_ID as CHAT_AUTHOR_ID,
2930 C.ENTITY_TYPE as CHAT_ENTITY_TYPE,
2931 C.ENTITY_ID as CHAT_ENTITY_ID,
2932 C.PARENT_ID as CHAT_PARENT_ID,
2933 C.PARENT_MID as CHAT_PARENT_MID,
2934 C.ENTITY_DATA_1 as CHAT_ENTITY_DATA_1,
2935 C.ENTITY_DATA_2 as CHAT_ENTITY_DATA_2,
2936 C.ENTITY_DATA_3 as CHAT_ENTITY_DATA_3,
2937 C.LAST_MESSAGE_ID as CHAT_LAST_MESSAGE_ID
2938 FROM b_im_message M
2939 LEFT JOIN b_im_chat C ON M.CHAT_ID = C.ID
2940 WHERE M.ID = ".$ID;
2941 $dbRes = $DB->Query($strSql);
2942 if ($arRes = $dbRes->Fetch())
2943 {
2944 $param = CIMMessageParam::Get($arRes['ID']);
2945 $arRes['PARAMS'] = $param? $param: Array();
2946 }
2947 if ($arRes && ($params['WITH_FILES'] ?? null) === 'Y')
2948 {
2949 $arFiles = Array();
2950 if (isset($arRes['PARAMS']['FILE_ID']))
2951 {
2952 foreach ($arRes['PARAMS']['FILE_ID'] as $fileId)
2953 {
2954 $arFiles[$fileId] = $fileId;
2955 }
2956 }
2957 $arRes['FILES'] = CIMDisk::GetFiles($arRes['CHAT_ID'], $arFiles, false);
2958 }
2959
2960 return $arRes;
2961 }
2962
2963 public static function GetRelationById($ID, bool $raw = false)
2964 {
2965 global $DB;
2966
2967 $ID = intval($ID);
2968 $chatId = null;
2969 $arResult = Array();
2970
2971 $strSql = "
2972 SELECT
2973 R.USER_ID, U.EXTERNAL_AUTH_ID, M.CHAT_ID
2974 FROM b_im_message M
2975 LEFT JOIN b_im_relation R ON M.CHAT_ID = R.CHAT_ID
2976 LEFT JOIN b_user U ON U.ID = R.USER_ID
2977 WHERE M.ID = ".$ID;
2978 $dbRes = $DB->Query($strSql);
2979 while ($arRes = $dbRes->Fetch())
2980 {
2981 $arResult[$arRes['USER_ID']] = $arRes;
2982 $chatId = (int)$arRes['CHAT_ID'];
2983 }
2984
2985 if (!$raw && $chatId)
2986 {
2988 }
2989
2990 return $arResult;
2991 }
2992
2993 public static function CheckXmppStatusOnline()
2994 {
2995 If (IsModuleInstalled('xmpp'))
2996 {
2997 $LastActivityDate = CUserOptions::GetOption('xmpp', 'LastActivityDate');
2998 if (intval($LastActivityDate)+60 > time())
2999 return true;
3000 }
3001 return false;
3002 }
3003
3004 public static function CheckEnableOpenChat()
3005 {
3006 return COption::GetOptionString('im', 'open_chat_enable');
3007 }
3008
3009 public static function CheckNetwork()
3010 {
3011 return COption::GetOptionString('bitrix24', 'network', 'N') == 'Y';
3012 }
3013
3014 public static function CheckNetwork2()
3015 {
3016 if (!CModule::IncludeModule('socialservices'))
3017 return false;
3018
3019 $network = new \Bitrix\Socialservices\Network();
3020 return $network->isEnabled();
3021 }
3022
3023 public static function CheckInstallDesktop()
3024 {
3025 $status = CIMStatus::GetStatus();
3026 if (
3027 is_array($status)
3028 && isset($status['DESKTOP_LAST_DATE'])
3029 && $status['DESKTOP_LAST_DATE']
3030 )
3031 {
3032 return true;
3033 }
3034
3035 return false;
3036 }
3037
3038 public static function EnableInVersion($version)
3039 {
3040 $version = intval($version);
3041 $currentVersion = intval(CUserOptions::GetOption('im', 'DesktopVersionApi', 0));
3042
3043 return $currentVersion >= $version;
3044 }
3045
3046 public static function IsDesktopEnvironment()
3047 {
3048 $userAgent = \Bitrix\Main\Context::getCurrent()->getServer()->get("HTTP_USER_AGENT");
3049 if (mb_strpos($userAgent, 'BitrixDesktop') === false)
3050 {
3051 return false;
3052 }
3053
3054 return true;
3055 }
3056
3057 public static function SetDesktopVersion($version)
3058 {
3059 global $USER;
3060
3061 $version = intval($version);
3062 $userId = intval($USER->GetId());
3063 if ($userId <= 0)
3064 return false;
3065
3066 $currentVersion = self::GetDesktopVersion();
3067 if ($currentVersion !== $version)
3068 {
3069 CUserOptions::SetOption('im', 'DesktopVersionApi', $version, false, $userId);
3070 }
3071
3072 return $version;
3073 }
3074
3075 public static function GetDesktopVersion()
3076 {
3077 $version = CUserOptions::GetOption('im', 'DesktopVersionApi', 0);
3078
3079 return (int)$version;
3080 }
3081
3082 public static function SetDesktopLastActivityDate($timestamp, $deviceType = IM_DESKTOP_WINDOWS, $userId = false)
3083 {
3084 if ($timestamp instanceof \Bitrix\Main\Type\DateTime)
3085 {
3086 $timestamp = $timestamp->getTimestamp();
3087 }
3088 else
3089 {
3090 $timestamp = (int)$timestamp;
3091 }
3092
3093 CIMStatus::Set($userId, Array('DESKTOP_LAST_DATE' => \Bitrix\Main\Type\DateTime::createFromTimestamp($timestamp)));
3094
3095 if ($deviceType === IM_DESKTOP_MAC)
3096 {
3097 $lastTimestamp = (int)CUserOptions::GetOption('im', 'MacLastActivityDate', -1, $userId);
3098 if ($lastTimestamp+86400*30 < time())
3099 {
3100 CUserOptions::SetOption('im', 'MacLastActivityDate', $timestamp, false, $userId);
3101 }
3102 }
3103 elseif ($deviceType === IM_DESKTOP_LINUX)
3104 {
3105 $lastTimestamp = (int)CUserOptions::GetOption('im', 'LinuxLastActivityDate', -1, $userId);
3106 if ($lastTimestamp+86400*30 < time())
3107 {
3108 CUserOptions::SetOption('im', 'LinuxLastActivityDate', $timestamp, false, $userId);
3109 }
3110 }
3111 else
3112 {
3113 $lastTimestamp = (int)CUserOptions::GetOption('im', 'WindowsLastActivityDate', -1, $userId);
3114 if ($lastTimestamp+86400*30 < time())
3115 {
3116 CUserOptions::SetOption('im', 'WindowsLastActivityDate', $timestamp, false, $userId);
3117 }
3118 }
3119 }
3120
3121 public static function CheckPhoneStatus()
3122 {
3123 if(!\Bitrix\Main\Loader::includeModule('voximplant') || !\Bitrix\Main\Loader::includeModule('pull'))
3124 return false;
3125
3126 return CPullOptions::GetNginxStatus() && (!IsModuleInstalled('extranet') || CModule::IncludeModule('extranet') && CExtranet::IsIntranetUser());
3127 }
3128
3129 public static function CanUserCallCrmNumber()
3130 {
3131 if(!\Bitrix\Main\Loader::includeModule('voximplant'))
3132 return false;
3133
3134 $userPermissions = \Bitrix\Voximplant\Security\Permissions::createWithCurrentUser();
3135 return $userPermissions->canPerform(
3136 \Bitrix\Voximplant\Security\Permissions::ENTITY_CALL,
3137 \Bitrix\Voximplant\Security\Permissions::ACTION_PERFORM,
3138 \Bitrix\Voximplant\Security\Permissions::PERMISSION_CALL_CRM
3139 );
3140 }
3141
3142 public static function CanUserCallUserNumber()
3143 {
3144 if(!\Bitrix\Main\Loader::includeModule('voximplant'))
3145 return false;
3146
3147 $userPermissions = \Bitrix\Voximplant\Security\Permissions::createWithCurrentUser();
3148 return $userPermissions->canPerform(
3149 \Bitrix\Voximplant\Security\Permissions::ENTITY_CALL,
3150 \Bitrix\Voximplant\Security\Permissions::ACTION_PERFORM,
3151 \Bitrix\Voximplant\Security\Permissions::PERMISSION_CALL_USERS
3152 );
3153 }
3154
3155 public static function CanCallByLimits()
3156 {
3157 if(!\Bitrix\Main\Loader::includeModule('voximplant'))
3158 {
3159 return false;
3160 }
3161
3162 return \Bitrix\Voximplant\Limits::canCall();
3163 }
3164
3165 public static function CanUserCallAnyNumber()
3166 {
3167 if(!\Bitrix\Main\Loader::includeModule('voximplant'))
3168 return false;
3169
3170 $userPermissions = \Bitrix\Voximplant\Security\Permissions::createWithCurrentUser();
3171 return $userPermissions->canPerform(
3172 \Bitrix\Voximplant\Security\Permissions::ENTITY_CALL,
3173 \Bitrix\Voximplant\Security\Permissions::ACTION_PERFORM,
3174 \Bitrix\Voximplant\Security\Permissions::PERMISSION_ANY
3175 );
3176 }
3177
3178 public static function CanUserPerformCalls()
3179 {
3180 if(!\Bitrix\Main\Loader::includeModule('voximplant'))
3181 return false;
3182
3183 $userPermissions = \Bitrix\Voximplant\Security\Permissions::createWithCurrentUser();
3184 return $userPermissions->canPerform(\Bitrix\Voximplant\Security\Permissions::ENTITY_CALL, \Bitrix\Voximplant\Security\Permissions::ACTION_PERFORM);
3185 }
3186
3187 public static function CanInterceptCall()
3188 {
3189 if(!\Bitrix\Main\Loader::includeModule('voximplant'))
3190 return false;
3191
3192 return \Bitrix\Voximplant\Limits::canInterceptCall();
3193 }
3194
3195
3196 public static function GetCallCardRestApps()
3197 {
3198 if(!\Bitrix\Main\Loader::includeModule('rest'))
3199 return array();
3200
3201 if(!\Bitrix\Main\Loader::includeModule('voximplant'))
3202 return array();
3203
3204 $result = array();
3205 if(!defined('Bitrix\Voximplant\Rest\Helper::PLACEMENT_CALL_CARD'))
3206 return array();
3207
3208 $placementId = Bitrix\Voximplant\Rest\Helper::PLACEMENT_CALL_CARD;
3209 $cursor = \Bitrix\Rest\PlacementTable::getHandlersList($placementId);
3210 foreach($cursor as $row)
3211 {
3212 $result[] = array(
3213 'id' => $row['ID'],
3214 'name' => $row['TITLE'] ?: $row['APP_NAME']
3215 );
3216 }
3217 return $result;
3218 }
3219
3220 public static function GetTelephonyAvailableLines($userId = null)
3221 {
3222 if(!\Bitrix\Main\Loader::includeModule('voximplant'))
3223 return array();
3224
3225 if(is_null($userId))
3226 $userId = self::GetCurrentUserId();
3227
3228 return \CVoxImplantUser::getAllowedLines($userId);
3229 }
3230
3231 public static function GetDefaultTelephonyLine($userId = null)
3232 {
3233 if(!\Bitrix\Main\Loader::includeModule('voximplant'))
3234 return '';
3235
3236 if(is_null($userId))
3237 $userId = self::GetCurrentUserId();
3238
3239 return CVoxImplantUser::getUserOutgoingLine($userId);
3240 }
3241
3242 public static function CheckDesktopStatusOnline($userId = null)
3243 {
3244 global $USER;
3245 if (is_null($userId))
3246 {
3247 $userId = $USER->GetId();
3248 }
3249
3250 $userId = intval($userId);
3251 if ($userId <= 0)
3252 {
3253 return false;
3254 }
3255
3256 $maxOnlineTime = 120;
3257 if (CModule::IncludeModule('pull') && CPullOptions::GetNginxStatus())
3258 {
3259 $maxOnlineTime = self::GetSessionLifeTime();
3260 }
3261
3262 $status = CIMStatus::GetStatus($userId);
3263 $desktopLastDateStatus = $status['DESKTOP_LAST_DATE'] ?? null;
3264
3265 if (
3266 $desktopLastDateStatus instanceof \Bitrix\Main\Type\DateTime
3267 && $desktopLastDateStatus->getTimestamp() + $maxOnlineTime + 60 > time()
3268 )
3269 {
3270 return true;
3271 }
3272
3273 return false;
3274 }
3275
3276 public static function GetDesktopStatusOnline($userId = null)
3277 {
3278 global $USER;
3279 if (is_null($userId))
3280 {
3281 $userId = $USER->GetId();
3282 }
3283
3284 $userId = intval($userId);
3285 if ($userId <= 0)
3286 {
3287 return 0;
3288 }
3289
3290 $status = CIMStatus::GetStatus($userId);
3291 if ($status['DESKTOP_LAST_DATE'] instanceof \Bitrix\Main\Type\DateTime)
3292 {
3293 return $status['DESKTOP_LAST_DATE']->getTimestamp();
3294 }
3295
3296 return 0;
3297 }
3298
3299 public static function SetDesktopStatusOnline($userId = null, $cache = true)
3300 {
3301 global $USER;
3302
3303 if (is_null($userId))
3304 $userId = $USER->GetId();
3305
3306 $userId = intval($userId);
3307 if ($userId <= 0)
3308 return false;
3309
3310 if ($cache && $userId == $USER->GetId())
3311 {
3312 if (
3313 isset(Application::getInstance()->getKernelSession()['IM']['SET_DESKTOP_ACTIVITY'])
3314 && intval(Application::getInstance()->getKernelSession()['IM']['SET_DESKTOP_ACTIVITY'])+300 > time()
3315 )
3316 {
3317 return false;
3318 }
3319
3320 Application::getInstance()->getKernelSession()['IM']['SET_DESKTOP_ACTIVITY'] = time();
3321 }
3322
3323 $userAgent = \Bitrix\Main\Context::getCurrent()->getRequest()->getUserAgent();
3324 if (mb_strpos(mb_strtolower($userAgent), "windows") !== false)
3325 {
3326 $deviceType = IM_DESKTOP_WINDOWS;
3327 }
3328 elseif (mb_strpos(mb_strtolower($userAgent), "macintosh") !== false)
3329 {
3330 $deviceType = IM_DESKTOP_MAC;
3331 }
3332 elseif (mb_strpos(mb_strtolower($userAgent), "linux") !== false)
3333 {
3334 $deviceType = IM_DESKTOP_LINUX;
3335 }
3336
3337 $time = time();
3338 \CIMMessenger::SetDesktopLastActivityDate($time, $deviceType, $userId);
3339
3340 if (CModule::IncludeModule("pull"))
3341 {
3342 if ($cache && $userId == $USER->GetId())
3343 {
3344 if (
3345 isset(Application::getInstance()->getKernelSession()['IM']['SET_DESKTOP_ACTIVITY_PULL'])
3346 && intval(Application::getInstance()->getKernelSession()['IM']['SET_DESKTOP_ACTIVITY_PULL'])+3600 > $time
3347 )
3348 {
3349 return false;
3350 }
3351
3352 Application::getInstance()->getKernelSession()['IM']['SET_DESKTOP_ACTIVITY_PULL'] = $time;
3353 }
3354
3356 'module_id' => 'im',
3357 'expiry' => 3600,
3358 'command' => 'desktopOnline',
3359 'params' => Array(
3360 'version' => CIMMessenger::GetDesktopVersion()
3361 ),
3362 'extra' => \Bitrix\Im\Common::getPullExtra()
3363 ));
3364
3366 }
3367
3368 return $time;
3369 }
3370
3371 public static function SetDesktopStatusOffline($userId = null)
3372 {
3373 global $USER;
3374
3375 if (is_null($userId))
3376 $userId = $USER->GetId();
3377
3378 $userId = intval($userId);
3379 if ($userId <= 0)
3380 return false;
3381
3382 unset(Application::getInstance()->getKernelSession()['IM']['SET_DESKTOP_ACTIVITY']);
3383 unset(Application::getInstance()->getKernelSession()['IM']['SET_DESKTOP_ACTIVITY_PULL']);
3384
3385 CIMStatus::Set($userId, Array('DESKTOP_LAST_DATE' => null));
3386
3387 if (CModule::IncludeModule("pull"))
3388 {
3390 'module_id' => 'im',
3391 'expiry' => 3600,
3392 'command' => 'desktopOffline',
3393 'params' => Array(),
3394 'extra' => \Bitrix\Im\Common::getPullExtra()
3395 ));
3396
3398 }
3399
3400 return true;
3401 }
3402
3403 public static function GetSettings($userId = false)
3404 {
3405 $arSettings = CIMSettings::Get($userId);
3406 return $arSettings['settings'];
3407 }
3408
3409 public static function GetFormatFilesMessageOut($files)
3410 {
3411 if (!is_array($files) || count($files) <= 0)
3412 return false;
3413
3414 $messageFiles = '';
3415 $serverName = (CMain::IsHTTPS() ? "https" : "http")."://".((defined("SITE_SERVER_NAME") && SITE_SERVER_NAME <> '') ? SITE_SERVER_NAME : COption::GetOptionString("main", "server_name", ""));
3416 foreach ($files as $fileId => $fileData)
3417 {
3418 if ($fileData['status'] == 'done')
3419 {
3420 $fileElement = $fileData['name'].' ('.CFile::FormatSize($fileData['size']).")\n".
3421 GetMessage('IM_MESSAGE_FILE_DOWN').' '.$serverName.$fileData['urlDownload']."\n";
3422 $messageFiles = $messageFiles <> ''? $messageFiles."\n".$fileElement: $fileElement;
3423 }
3424 }
3425
3426 return $messageFiles;
3427 }
3428
3429 public static function GetSessionLifeTime()
3430 {
3431 global $USER;
3432
3433 $sessTimeout = CUser::GetSecondsForLimitOnline();
3434 if ($USER instanceof CUser)
3435 {
3436 $arPolicy = $USER->GetSecurityPolicy();
3437 if($arPolicy["SESSION_TIMEOUT"] > 0)
3438 {
3439 $sessTimeout = min($arPolicy["SESSION_TIMEOUT"]*60, $sessTimeout);
3440 }
3441 }
3442
3443 $sessTimeout = intval($sessTimeout);
3444 if ($sessTimeout <= 120)
3445 {
3446 $sessTimeout = 100;
3447 }
3448
3449 return intval($sessTimeout);
3450 }
3451
3452 public static function GetUnreadCounter($userId)
3453 {
3454 //todo return counters for user
3455 return (new \Bitrix\Im\V2\Message\CounterService($userId))->getForNotifyChat();
3456 //$count = 0;
3457 /*$userId = intval($userId);
3458 if ($userId <= 0)
3459 return $count;
3460
3461 global $DB;
3462
3463 $strSql ="
3464 SELECT M.ID, M.NOTIFY_TYPE, M.NOTIFY_TAG
3465 FROM b_im_message M
3466 INNER JOIN b_im_relation R1 ON M.ID > R1.LAST_ID AND M.CHAT_ID = R1.CHAT_ID AND R1.USER_ID != M.AUTHOR_ID
3467 WHERE R1.USER_ID = ".$userId." AND R1.STATUS < ".IM_STATUS_READ."
3468 ";
3469
3470 $dbRes = $DB->Query($strSql);
3471
3472 $arGroupNotify = Array();
3473 while ($arRes = $dbRes->Fetch())
3474 {
3475 if ($arRes['NOTIFY_TYPE'] == 2 && $arRes['NOTIFY_TAG'] != '')
3476 {
3477 if (!isset($arGroupNotify[$arRes['NOTIFY_TAG']]))
3478 {
3479 $arGroupNotify[$arRes['NOTIFY_TAG']] = true;
3480 $count++;
3481 }
3482 }
3483 else
3484 $count++;
3485 }*/
3486
3487 //return $count;
3488 }
3489
3490 public static function GetMessageCounter($userId, $arMessages = Array())
3491 {
3492 $count = 0;
3493 if (isset($arMessages['message']))
3494 {
3495 foreach ($arMessages['message'] as $value)
3496 $count += isset($value['counter'])? $value['counter']: 1;
3497 }
3498 else
3499 {
3501 }
3502
3503 return intval($count);
3504 }
3505
3506 private static function GetReasonForMessageSendError($type = IM_MESSAGE_PRIVATE, $reason = '')
3507 {
3508 if (!empty($reason))
3509 {
3510 $CBXSanitizer = new CBXSanitizer;
3511 $CBXSanitizer->AddTags(array(
3512 'a' => array('href','style', 'target'),
3513 'b' => array(), 'u' => array(),
3514 'i' => array(), 'br' => array(),
3515 'span' => array('style'),
3516 ));
3517 $reason = $CBXSanitizer->SanitizeHtml($reason);
3518 }
3519 else
3520 {
3522 {
3523 $reason = GetMessage("IM_ERROR_MESSAGE_CANCELED");
3524 }
3525 else if ($type == IM_MESSAGE_SYSTEM)
3526 {
3527 $reason = GetMessage("IM_ERROR_NOTIFY_CANCELED");
3528 }
3529 else
3530 {
3531 $reason = GetMessage("IM_ERROR_GROUP_CANCELED");
3532 }
3533 }
3534
3535 return $reason;
3536 }
3537
3538 public static function SpeedFileCreate($userID, $value, $type = IM_SPEED_MESSAGE)
3539 {
3540 global $CACHE_MANAGER;
3541
3542 $userID = intval($userID);
3543 if ($userID <= 0 || !in_array($type, Array(IM_SPEED_NOTIFY, IM_SPEED_MESSAGE, IM_SPEED_GROUP)))
3544 return false;
3545
3546 $CACHE_MANAGER->Clean("im_csf_v2_".$type.'_'.$userID);
3547 $CACHE_MANAGER->Read(86400*30, "im_csf_v2_".$type.'_'.$userID);
3548 $CACHE_MANAGER->Set("im_csf_v2_".$type.'_'.$userID, $value);
3549 }
3550
3551 public static function SpeedFileDelete($userID, $type = IM_SPEED_MESSAGE)
3552 {
3553 global $CACHE_MANAGER;
3554
3555 $userID = intval($userID);
3556 if ($userID <= 0 || !in_array($type, Array(IM_SPEED_NOTIFY, IM_SPEED_MESSAGE, IM_SPEED_GROUP)))
3557 return false;
3558
3559 $CACHE_MANAGER->Clean("im_csf_v2_".$type.'_'.$userID);
3560 }
3561
3562 public static function SpeedFileExists($userID, $type = IM_SPEED_MESSAGE)
3563 {
3564 global $CACHE_MANAGER;
3565
3566 $userID = intval($userID);
3567 if ($userID <= 0 || !in_array($type, Array(IM_SPEED_NOTIFY, IM_SPEED_MESSAGE, IM_SPEED_GROUP)))
3568 return false;
3569
3570 $result = $CACHE_MANAGER->Read(86400*30, "im_csf_v2_".$type.'_'.$userID);
3571 if ($result)
3572 $result = $CACHE_MANAGER->Get("im_csf_v2_".$type.'_'.$userID) === false? false: true;
3573
3574 return $result;
3575 }
3576
3577 public static function SpeedFileGet($userID, $type = IM_SPEED_MESSAGE)
3578 {
3579 global $CACHE_MANAGER;
3580
3581 $userID = intval($userID);
3582 if ($userID <= 0 || !in_array($type, Array(IM_SPEED_NOTIFY, IM_SPEED_MESSAGE, IM_SPEED_GROUP)))
3583 return false;
3584
3585 $CACHE_MANAGER->Read(86400*30, "im_csf_v2_".$type.'_'.$userID);
3586 return $CACHE_MANAGER->Get("im_csf_v2_".$type.'_'.$userID);
3587 }
3588
3589 public static function GetTemplateJS($arParams, $arTemplate)
3590 {
3591 global $USER;
3592
3593 $ppStatus = 'false';
3594 $ppServerStatus = 'false';
3595 $updateStateInterval = 'auto';
3596 if (CModule::IncludeModule("pull"))
3597 {
3598 $ppStatus = CPullOptions::ModuleEnable()? 'true': 'false';
3599 $ppServerStatus = CPullOptions::GetNginxStatus()? 'true': 'false';
3600
3601 $updateStateInterval = CPullOptions::GetNginxStatus()? self::GetSessionLifeTime(): 80;
3602 if ($updateStateInterval > 100)
3603 {
3604 if ($updateStateInterval > 3600)
3605 $updateStateInterval = 3600;
3606
3607 if (in_array($arTemplate["CONTEXT"], Array("POPUP-FULLSCREEN", "MESSENGER")))
3608 $updateStateInterval = $updateStateInterval-60;
3609 else
3610 $updateStateInterval = intval($updateStateInterval/2)-10;
3611 }
3612 }
3613
3614 $diskStatus = CIMDisk::Enabled();
3615 $diskExternalLinkStatus = CIMDisk::EnabledExternalLink();
3616
3617 $phoneCanPerformCalls = false;
3618 $phoneDeviceActive = false;
3619 $phoneCanCallUserNumber = false;
3620 $phoneEnabled = false;
3621 $chatExtendShowHistory = \COption::GetOptionInt('im', 'chat_extend_show_history');
3622 $contactListLoad = \COption::GetOptionInt('im', 'contact_list_load');
3623 $contactListBirthday = \COption::GetOptionString('im', 'contact_list_birthday');
3624 $isFullTextEnabled = \Bitrix\Im\Model\MessageIndexTable::getEntity()->fullTextIndexEnabled("SEARCH_CONTENT");
3626 $phoneCanInterceptCall = self::CanInterceptCall();
3627
3628 if ($arTemplate['INIT'] == 'Y')
3629 {
3630 $phoneEnabled = self::CheckPhoneStatus();
3631 if ($phoneEnabled && CModule::IncludeModule('voximplant'))
3632 {
3633 $phoneCanPerformCalls = self::CanUserPerformCalls();
3634 $phoneDeviceActive = CVoxImplantUser::GetPhoneActive($USER->GetId());
3635 $phoneCanCallUserNumber = self::CanUserCallUserNumber();
3636 }
3637 }
3638
3639 $counters = \Bitrix\Im\Counter::get(null, ['JSON' => 'Y']);
3640 $counters['type']['mail'] = isset($arParams['MAIL_COUNTER']) ? (int)$arParams['MAIL_COUNTER'] : 0;
3641
3642 $crmPath = Array();
3643 $olConfig = Array();
3644 $businessUsers = false;
3645
3646 if (\Bitrix\Main\Loader::includeModule('crm'))
3647 {
3648 $crmPath['LEAD'] = \Bitrix\Im\Integration\Crm\Common::getLink('LEAD');
3649 $crmPath['CONTACT'] = \Bitrix\Im\Integration\Crm\Common::getLink('CONTACT');
3650 $crmPath['COMPANY'] = \Bitrix\Im\Integration\Crm\Common::getLink('COMPANY');
3651 $crmPath['DEAL'] = \Bitrix\Im\Integration\Crm\Common::getLink('DEAL');
3652 }
3653
3654 if (\Bitrix\Main\Loader::includeModule('imopenlines'))
3655 {
3656 $olConfig['canDeleteMessage'] = str_replace('.', '_', \Bitrix\Imopenlines\Connector::getListCanDeleteMessage());
3657 $olConfig['canDeleteOwnMessage'] = str_replace('.', '_', \Bitrix\Imopenlines\Connector::getListCanDeleteOwnMessage());
3658 $olConfig['canUpdateOwnMessage'] = str_replace('.', '_', \Bitrix\Imopenlines\Connector::getListCanUpdateOwnMessage());
3659
3660 $olConfig['queue'] = Array();
3661 foreach (\Bitrix\ImOpenLines\Config::getQueueList($USER->GetID()) as $config)
3662 {
3663 $olConfig['queue'][] = array_change_key_case($config, CASE_LOWER);
3664 }
3665
3666 foreach (\Bitrix\ImOpenLines\Config::getAllLinesSettings(['CONFIRM_CLOSE']) as $config)
3667 {
3668 $lineId = (int)$config['ID'];
3669 $olConfig['settings'][$lineId] = array_change_key_case($config, CASE_LOWER);
3670
3671 $connectorStatus = \Bitrix\ImConnector\Status::getInstance(\Bitrix\ImOpenLines\Connector::TYPE_NETWORK, $lineId);
3672 if ($connectorStatus->isStatus())
3673 {
3674 $connectorData = $connectorStatus->getData();
3675 if (isset($connectorData['MULTIDIALOG']) && $connectorData['MULTIDIALOG'] === 'Y')
3676 {
3677 $olConfig['settings'][$lineId]['multidialog'] = 'Y';
3678 }
3679 else
3680 {
3681 $olConfig['settings'][$lineId]['multidialog'] = 'N';
3682 }
3683 }
3684 }
3685
3686 $olConfig['canUseVoteHead'] = Imopenlines\Limit::canUseVoteHead();
3687 $olConfig['canJoinChatUser'] = Imopenlines\Limit::canJoinChatUser();
3688 $olConfig['canTransferToLine'] = Imopenlines\Limit::canTransferToLine();
3689 }
3690
3691 $bitrix24blocked = false;
3692 $bitrix24Enabled = false;
3693 $bitrixPaid = true;
3694 if (\Bitrix\Main\Loader::includeModule('bitrix24'))
3695 {
3696 $bitrix24Enabled = true;
3697 $bitrixPaid = CBitrix24::IsLicensePaid() || CBitrix24::IsNfrLicense();
3699 {
3700 $bitrix24blocked = \Bitrix\Bitrix24\Limits\User::getUserRestrictedHelperCode();
3701 }
3702 }
3703
3705
3706 $pathToIm = isset($arTemplate['PATH_TO_IM']) ? $arTemplate['PATH_TO_IM'] : '';
3707 $pathToCall = isset($arTemplate['PATH_TO_CALL']) ? $arTemplate['PATH_TO_CALL'] : '';
3708 $pathToFile = isset($arTemplate['PATH_TO_FILE']) ? $arTemplate['PATH_TO_FILE'] : '';
3709 $pathToLf = isset($arTemplate['PATH_TO_LF']) ? $arTemplate['PATH_TO_LF'] : '/';
3710 $pathToDisk = Array(
3711 'localFile' => \CIMDisk::GetLocalDiskFilePath(),
3712 );
3713
3714 $recentLastUpdate = (new \Bitrix\Main\Type\DateTime())->format(\DateTimeInterface::RFC3339);
3715 $recent = \Bitrix\Im\Recent::getList(null, [
3716 'SKIP_NOTIFICATION' => 'Y',
3717 'SKIP_OPENLINES' => 'Y',
3718 'JSON' => 'Y',
3719 'GET_ORIGINAL_TEXT' => 'Y',
3720 //'SHORT_INFO' => 'Y',
3721 ]);
3722
3723 $iframeRequest = $_REQUEST['IFRAME'] ?? null;
3724 $iframeTypeRequest = $_REQUEST['IFRAME_TYPE'] ?? null;
3725 $imMenuRequest = $_REQUEST['IM_MENU'] ?? null;
3726 $imSearchRequest = $_REQUEST['IM_SEARCH'] ?? null;
3727 $imStatusRequest = $_REQUEST['IM_STATUS'] ?? null;
3728 $imRecentRequest = $_REQUEST['IM_RECENT'] ?? null;
3729 $imLinesRequest = $_REQUEST['IM_LINES'] ?? null;
3730 $imV2LayoutRequest = $_REQUEST['IM_V2_LAYOUT'] ?? null;
3731 if (!isset($_REQUEST['IM_BACKGROUND']))
3732 {
3733 $imBackgroundRequest = 'auto';
3734 }
3735 else
3736 {
3737 $imBackgroundRequest = $_REQUEST['IM_BACKGROUND'] === 'dark'? 'dark': 'light';
3738 }
3739
3740 if (is_bool($arTemplate["DESKTOP"]))
3741 {
3742 $arTemplate["DESKTOP"] = $arTemplate["DESKTOP"] ? 'true' : 'false';
3743 }
3744
3745 $sJS = "
3746 BX.ready(function() {
3747 BXIM = new BX.IM(BX('bx-notifier-panel'), {
3748 'init': ".($arTemplate['INIT'] == 'Y'? 'true': 'false').",
3749 'context': '".$arTemplate["CONTEXT"]."',
3750 'design': '".$arTemplate["DESIGN"]."',
3753 'chatCounters': ".\Bitrix\Im\Common::objectEncode($counters, true).",
3754 'counters': ".(empty($arTemplate['COUNTERS'])? '{}': \Bitrix\Im\Common::objectEncode($arTemplate['COUNTERS'])).",
3755 'ppStatus': ".$ppStatus.",
3756 'ppServerStatus': ".$ppServerStatus.",
3757 'updateStateInterval': '".$updateStateInterval."',
3758 'openChatEnable': ".(CIMMessenger::CheckEnableOpenChat()? 'true': 'false').",
3759 'xmppStatus': ".(CIMMessenger::CheckXmppStatusOnline()? 'true': 'false').",
3760 'isAdmin': ".(self::IsAdmin()? 'true': 'false').",
3761 'canInvite': ".(\Bitrix\Im\Integration\Intranet\User::canInvite()? 'true': 'false').",
3762 'isLinesOperator': 'true',
3763 'isUtfMode': true,
3764 'bitrixNetwork': ".(CIMMessenger::CheckNetwork()? 'true': 'false').",
3765 'bitrix24': ".($bitrix24Enabled? 'true': 'false').",
3766 'bitrix24blocked': ".($bitrix24blocked? $bitrix24blocked: 'false').",
3767 'bitrix24net': ".(IsModuleInstalled('b24network')? 'true': 'false').",
3768 'bitrixPaid': ".($bitrixPaid? 'true': 'false').",
3769 'bitrixIntranet': ".(IsModuleInstalled('intranet')? 'true': 'false').",
3770 'bitrixXmpp': ".(IsModuleInstalled('xmpp')? 'true': 'false').",
3771 'bitrixMobile': ".(IsModuleInstalled('mobile')? 'true': 'false').",
3772 'bitrixOpenLines': ".(IsModuleInstalled('imopenlines')? 'true': 'false').",
3773 'bitrixCrm': ".(IsModuleInstalled('crm')? 'true': 'false').",
3774 'desktop': ".($arTemplate["DESKTOP"] ?? 'false').",
3775 'desktopStatus': ".(CIMMessenger::CheckDesktopStatusOnline()? 'true': 'false').",
3776 'desktopVersion': ".CIMMessenger::GetDesktopVersion().",
3777 'desktopLinkOpen': ".($arTemplate["DESKTOP_LINK_OPEN"] ?? 'false').",
3778 'language': '".LANGUAGE_ID."',
3779 'loggerConfig': ".\Bitrix\Im\Common::objectEncode(\Bitrix\Im\Settings::getLoggerConfig(), true).",
3780 'broadcastingEnabled': ".\Bitrix\Im\Common::objectEncode(\Bitrix\Im\Settings::isBroadcastingEnabled(), true).",
3781 'tooltipShowed': ".\Bitrix\Im\Common::objectEncode(CUserOptions::GetOption('im', 'tooltipShowed', array())).",
3782 'limit': ".(empty($arTemplate['LIMIT'])? 'false': \Bitrix\Im\Common::objectEncode($arTemplate["LIMIT"])).",
3783 'promo': ".(empty($arTemplate['PROMO'])? '[]': \Bitrix\Im\Common::objectEncode($arTemplate["PROMO"])).",
3784 'bot': ".(empty($arTemplate['BOT'])? '{}': \Bitrix\Im\Common::objectEncode($arTemplate["BOT"])).",
3785 'textareaIcon': ".(empty($arTemplate['TEXTAREA_ICON'])? '{}': \Bitrix\Im\Common::objectEncode($arTemplate["TEXTAREA_ICON"])).",
3786 'command': ".(empty($arTemplate['COMMAND'])? '[]': \Bitrix\Im\Common::objectEncode($arTemplate["COMMAND"])).",
3787
3788 'smile': ".\Bitrix\Im\Common::objectEncode($arTemplate["SMILE"]).",
3789 'smileSet': ".\Bitrix\Im\Common::objectEncode($arTemplate["SMILE_SET"]).",
3790 'settings': ".\Bitrix\Im\Common::objectEncode($arTemplate['SETTINGS']).",
3791 'settingsNotifyBlocked': ".(empty($arTemplate['SETTINGS_NOTIFY_BLOCKED'])? '{}': \Bitrix\Im\Common::objectEncode($arTemplate['SETTINGS_NOTIFY_BLOCKED'])).",
3792
3793 'recent': ".\Bitrix\Im\Common::objectEncode($recent, true).",
3794 'recentLastUpdate': '".$recentLastUpdate."',
3795 'businessUsers': ".($businessUsers === false? 'false': (empty($businessUsers)? '{}': \Bitrix\Im\Common::objectEncode($businessUsers))).",
3796 'userChatOptions': ".\Bitrix\Im\Common::objectEncode(CIMChat::GetChatOptions()).",
3797 'historyOptions' : ".\Bitrix\Im\Common::objectEncode(['fullTextEnabled' => $isFullTextEnabled, 'ftMinSizeToken' => $fullTextMinSizeToken]).",
3798 'openMessenger' : ".(isset($_REQUEST['IM_DIALOG'])? "'".CUtil::JSEscape(htmlspecialcharsbx($_REQUEST['IM_DIALOG']))."'": 'false').",
3799 'openHistory' : ".(isset($_REQUEST['IM_HISTORY'])? "'".CUtil::JSEscape(htmlspecialcharsbx($_REQUEST['IM_HISTORY']))."'": 'false').",
3800 'openNotify' : ".(isset($_GET['IM_NOTIFY']) && $_GET['IM_NOTIFY'] == 'Y'? 'true': 'false').",
3801 'openSettings' : ".(isset($_GET['IM_SETTINGS'])? $_GET['IM_SETTINGS'] == 'Y'? "'true'": "'".CUtil::JSEscape(htmlspecialcharsbx($_GET['IM_SETTINGS']))."'": 'false').",
3802 'externalRecentList' : '".(isset($arTemplate['EXTERNAL_RECENT_LIST'])?$arTemplate['EXTERNAL_RECENT_LIST']: '')."',
3803
3804 'generalChatId': ".CIMChat::GetGeneralChatId().",
3805 'canSendMessageGeneralChat': ".(CIMChat::CanSendMessageToGeneralChat($USER->GetID())? 'true': 'false').",
3806 'debug': ".(defined('IM_DEBUG')? 'true': 'false').",
3807 'next': ".(defined('IM_NEXT')? 'true': 'false').",
3808 'userId': ".$USER->GetID().",
3809 'userEmail': '".CUtil::JSEscape($USER->GetEmail())."',
3810 'userColor': '".\Bitrix\Im\Color::getCode(\Bitrix\Im\User::getInstance()->getColor())."',
3811 'userGender': '".\Bitrix\Im\User::getInstance()->getGender()."',
3812 'userExtranet': ".(\Bitrix\Im\User::getInstance()->isExtranet()? 'true': 'false').",
3813 'user': ".($arTemplate['CURRENT_USER']? \Bitrix\Im\Common::objectEncode($arTemplate['CURRENT_USER']): '{}').",
3814 'userBirthday': ".(!empty($userBirthday)? \Bitrix\Im\Common::objectEncode($userBirthday): '[]').",
3815 'webrtc': {
3816 'turnServer' : '".CUtil::JSEscape($arTemplate['TURN_SERVER'])."',
3817 'turnServerFirefox' : '".CUtil::JSEscape($arTemplate['TURN_SERVER_FIREFOX'])."',
3818 'turnServerLogin' : '".CUtil::JSEscape($arTemplate['TURN_SERVER_LOGIN'])."',
3819 'turnServerPassword' : '".CUtil::JSEscape($arTemplate['TURN_SERVER_PASSWORD'])."',
3820 'bitrixCallEnabled': ".(\Bitrix\Im\Call\Call::isCallServerEnabled() ? 'true' : 'false').",
3821 'mobileSupport': false,
3822 'phoneEnabled': ".($phoneEnabled? 'true': 'false').",
3823 'phoneDeviceActive': '".($phoneDeviceActive? 'Y': 'N')."',
3824 'phoneCanPerformCalls': '".($phoneCanPerformCalls? 'Y': 'N')."',
3825 'phoneCanCallUserNumber': '".($phoneCanCallUserNumber? 'Y': 'N')."',
3826 'phoneCanInterceptCall': ".($phoneCanInterceptCall? 'true': 'false').",
3827 'phoneCallCardRestApps': ".\Bitrix\Im\Common::objectEncode(self::GetCallCardRestApps()).",
3828 'phoneDefaultLineId': '".self::GetDefaultTelephonyLine()."',
3829 'availableLines': ".\Bitrix\Im\Common::objectEncode(self::GetTelephonyAvailableLines()).",
3830 'formatRecordDate': '".\Bitrix\Main\Context::getCurrent()->getCulture()->getShortDateFormat()."'
3831 },
3832 'openlines': ".\Bitrix\Im\Common::objectEncode($olConfig).",
3833 'options': {'contactListLoad' : ".($contactListLoad? 'true': 'false').", 'contactListBirthday' : '".$contactListBirthday."', 'chatExtendShowHistory' : ".($chatExtendShowHistory? 'true': 'false').", 'frameMode': ".($iframeRequest === 'Y'? 'true': 'false').", 'frameType': '".($iframeTypeRequest === 'SIDE_SLIDER'? 'SIDE_SLIDER': 'NONE')."', 'showRecent': ".($imRecentRequest === 'N'? 'false': 'true').", 'showMenu': ".($imMenuRequest === 'N'? 'false': 'true').", 'showSearch': ".($imSearchRequest === 'N'? 'false': 'true').", 'showStatus': ".($imStatusRequest === 'N'? 'false': 'true').", 'openLinesRecent': ".($imLinesRequest === 'Y'? 'true': 'false').", 'v2layout': ".($imV2LayoutRequest === 'Y'? 'true': 'false').", 'background': '".$imBackgroundRequest."'},
3834 'disk': {'enable' : ".($diskStatus? 'true': 'false').", 'external' : ".($diskExternalLinkStatus? 'true': 'false')."},
3835 'zoomStatus': {'active' : ".(\Bitrix\Im\Call\Integration\Zoom::isActive()? 'true': 'false').", 'enabled' : ".(\Bitrix\Im\Call\Integration\Zoom::isAvailable()? 'true': 'false').", 'connected' : ".(\Bitrix\Im\Call\Integration\Zoom::isConnected($USER->GetID())? 'true': 'false')."},
3836 'path' : {'lf' : '".CUtil::JSEscape($pathToLf)."', 'profile' : '".CUtil::JSEscape($arTemplate['PATH_TO_USER_PROFILE'])."', 'profileTemplate' : '".CUtil::JSEscape($arTemplate['PATH_TO_USER_PROFILE_TEMPLATE'])."', 'mail' : '".CUtil::JSEscape($arTemplate['PATH_TO_USER_MAIL'])."', 'im': '".CUtil::JSEscape($pathToIm)."', 'call': '".CUtil::JSEscape($pathToCall)."', 'file': '".CUtil::JSEscape($pathToFile)."', 'crm' : ".\Bitrix\Im\Common::objectEncode($crmPath).", 'disk' : ".\Bitrix\Im\Common::objectEncode($pathToDisk)."}
3837 });
3838 });
3839 ";
3840
3841 return $sJS;
3842 }
3843
3844 public static function GetV2TemplateJS($arResult): string
3845 {
3846 $isDesktop = $arResult['DESKTOP'] === true;
3847 $appName =
3848 $isDesktop
3849 ? \Bitrix\Im\V2\Application::MESSENGER_APP_NAME
3850 : \Bitrix\Im\V2\Application::QUICK_ACCESS_APP_NAME
3851 ;
3853
3854 return $application->getTemplate($appName);
3855 }
3856
3857 public static function getPhoneSettings(): array
3858 {
3859 global $USER;
3860
3861 $phoneEnabled = self::CheckPhoneStatus();
3862 $phoneDeviceActive = false;
3863 $phoneCanPerformCallsByUser = false;
3864 $phoneCanPerformCallsByLimits = false;
3865 $phoneCanCallUserNumber = false;
3866 if ($phoneEnabled && CModule::IncludeModule('voximplant'))
3867 {
3868 $phoneDeviceActive = CVoxImplantUser::GetPhoneActive($USER->GetId());
3869 $phoneCanPerformCallsByUser = self::CanUserPerformCalls();
3870 $phoneCanCallUserNumber = self::CanUserCallUserNumber();
3871 $phoneCanPerformCallsByLimits = self::CanCallByLimits();
3872 }
3873
3874 return [
3875 'phoneEnabled' => $phoneEnabled,
3876 'deviceActive' => $phoneDeviceActive,
3877 'defaultLineId' => self::GetDefaultTelephonyLine(),
3878 'availableLines' => self::GetTelephonyAvailableLines(),
3879 'canInterceptCall' => self::CanInterceptCall(),
3880 'canPerformCallsByUser' => $phoneCanPerformCallsByUser,
3881 'canPerformCallsByLimits' => $phoneCanPerformCallsByLimits,
3882 'canCallUserNumber' => $phoneCanCallUserNumber,
3883 'restApps' => self::GetCallCardRestApps()
3884 ];
3885 }
3886
3888 {
3889 global $USER;
3890
3891 $ppStatus = false;
3892 $ppServerStatus = false;
3893 $updateStateInterval = 'auto';
3894 if (CModule::IncludeModule("pull"))
3895 {
3896 $ppStatus = (bool)CPullOptions::ModuleEnable();
3897 $ppServerStatus = (bool)CPullOptions::GetNginxStatus();
3898 $updateStateInterval = CPullOptions::GetNginxStatus()? self::GetSessionLifeTime(): 80;
3899 if ($updateStateInterval > 100)
3900 {
3901 if ($updateStateInterval > 3600)
3902 $updateStateInterval = 3600;
3903
3904 $updateStateInterval = $updateStateInterval-60;
3905 }
3906 }
3907
3908 $diskStatus = CIMDisk::Enabled();
3909 $diskExternalLinkStatus = CIMDisk::EnabledExternalLink();
3910
3911 $chatExtendShowHistory = \COption::GetOptionInt('im', 'chat_extend_show_history');
3912
3913 $phoneEnabled = self::CheckPhoneStatus() && CModule::IncludeModule('mobileapp') && \Bitrix\MobileApp\Mobile::getInstance()->isWebRtcSupported();
3914
3915 $olConfig = Array();
3916 $crmPath = Array();
3917 $businessUsers = false;
3918
3919 if (\Bitrix\Main\Loader::includeModule('crm'))
3920 {
3921 $crmPath['LEAD'] = \Bitrix\Im\Integration\Crm\Common::getLink('LEAD');
3922 $crmPath['CONTACT'] = \Bitrix\Im\Integration\Crm\Common::getLink('CONTACT');
3923 $crmPath['COMPANY'] = \Bitrix\Im\Integration\Crm\Common::getLink('COMPANY');
3924 $crmPath['DEAL'] = \Bitrix\Im\Integration\Crm\Common::getLink('DEAL');
3925 }
3926
3927 if (CModule::IncludeModule('imopenlines'))
3928 {
3929 $olConfig['canDeleteMessage'] = str_replace('.', '_', \Bitrix\Imopenlines\Connector::getListCanDeleteMessage());
3930 $olConfig['canDeleteOwnMessage'] = str_replace('.', '_', \Bitrix\Imopenlines\Connector::getListCanDeleteOwnMessage());
3931 $olConfig['canUpdateOwnMessage'] = str_replace('.', '_', \Bitrix\Imopenlines\Connector::getListCanUpdateOwnMessage());
3932 $olConfig['queue'] = Array();
3933 foreach (\Bitrix\ImOpenLines\Config::getQueueList($USER->GetID()) as $config)
3934 {
3935 $olConfig['queue'][] = array_change_key_case($config, CASE_LOWER);
3936 }
3937 }
3938
3939 $mobileAction = isset($arTemplate["ACTION"])? $arTemplate["ACTION"]: 'none';
3940 $mobileCallMethod = isset($arTemplate["CALL_METHOD"])? $arTemplate["CALL_METHOD"]: 'device';
3941
3942 $counters = \Bitrix\Im\Counter::get(null, ['JSON' => 'Y']);
3943
3944 $initConfig = [
3945 'mobileAction' => $mobileAction,
3946 'mobileCallMethod' => $mobileCallMethod,
3948 'chatCounters' => [
3949 'notify' => intval($counters['TYPE']['NOTIFY']),
3950 'dialog' => intval($counters['TYPE']['DIALOG']),
3951 'chat' => intval($counters['TYPE']['CHAT']),
3952 'lines' => intval($counters['TYPE']['LINES']),
3953 'mail' => intval($arTemplate["MAIL_COUNTER"])
3954 ],
3955 'counters' => empty($arTemplate['COUNTERS'])? false: $arTemplate['COUNTERS'],
3956 'ppStatus' => $ppStatus,
3957 'ppServerStatus' => $ppServerStatus,
3958 'updateStateInterval' => $updateStateInterval,
3959 'openChatEnable' => (bool)CIMMessenger::CheckEnableOpenChat(),
3960 'xmppStatus' => (bool)CIMMessenger::CheckXmppStatusOnline(),
3961 'isAdmin' => (bool)self::IsAdmin(),
3962 'bitrixNetwork' => (bool)CIMMessenger::CheckNetwork(),
3963 'bitrix24' => (bool)IsModuleInstalled('bitrix24'),
3964 'bitrix24net' => (bool)IsModuleInstalled('b24network'),
3965 'bitrixIntranet' => (bool)IsModuleInstalled('intranet'),
3966 'bitrixXmpp' => (bool)IsModuleInstalled('xmpp'),
3967 'bitrixMobile' => (bool)IsModuleInstalled('mobile'),
3968 'bitrixOpenLines' => (bool)IsModuleInstalled('imopenlines'),
3969 'bitrixCrm' => (bool)IsModuleInstalled('crm'),
3970 'desktopStatus' => (bool)CIMMessenger::CheckDesktopStatusOnline(),
3971 'desktopVersion' => (int)CIMMessenger::GetDesktopVersion(),
3972 'language' => LANGUAGE_ID,
3973
3974 'bot' => empty($arTemplate['BOT'])? false: $arTemplate["BOT"],
3975 'command' => empty($arTemplate['COMMAND'])? false: $arTemplate["COMMAND"],
3976 'textareaIcon' => empty($arTemplate['TEXTAREA_ICON'])? false: $arTemplate["TEXTAREA_ICON"],
3977
3978 'smile' => empty($arTemplate['SMILE'])? false: $arTemplate["SMILE"],
3979 'smileSet' => empty($arTemplate['SMILE_SET'])? false: $arTemplate["SMILE_SET"],
3980 'settings' => empty($arTemplate['SETTINGS'])? false: $arTemplate['SETTINGS'],
3981 'settingsNotifyBlocked' => empty($arTemplate['SETTINGS_NOTIFY_BLOCKED'])? false: $arTemplate['SETTINGS_NOTIFY_BLOCKED'],
3982
3983 'recent' => false,
3984 'businessUsers' => $businessUsers === false? false: (empty($businessUsers)? null: $businessUsers),
3985 'userChatOptions' => CIMChat::GetChatOptions(),
3986 'history' => false,
3987 'openMessenger' => false,
3988 'openHistory' => false,
3989 'openNotify' => false,
3990 'openSettings' => false,
3991
3992 'generalChatId' => CIMChat::GetGeneralChatId(),
3993 'canSendMessageGeneralChat' => (bool)CIMChat::CanSendMessageToGeneralChat($USER->GetID()),
3994 'userId' => $USER->GetID(),
3995 'userEmail' => $USER->GetEmail(),
3996 'userColor' => \Bitrix\Im\Color::getCode(\Bitrix\Im\User::getInstance()->getColor()),
3997 'userGender' => \Bitrix\Im\User::getInstance()->getGender(),
3998 'userExtranet' => (bool)\Bitrix\Im\User::getInstance()->isExtranet(),
3999 'webrtc' => [
4000 'turnServer' => empty($arTemplate['TURN_SERVER'])? '': $arTemplate['TURN_SERVER'],
4001 'turnServerLogin' => empty($arTemplate['TURN_SERVER_LOGIN'])? '': $arTemplate['TURN_SERVER_LOGIN'],
4002 'turnServerPassword' => empty($arTemplate['TURN_SERVER_PASSWORD'])? '': $arTemplate['TURN_SERVER_PASSWORD'],
4003 'mobileSupport' => (bool)$arTemplate['WEBRTC_MOBILE_SUPPORT'],
4004 'phoneEnabled' => (bool)$phoneEnabled,
4005 ],
4006 'openlines' => $olConfig,
4007 'options' => [
4008 'chatExtendShowHistory' => (bool)$chatExtendShowHistory
4009 ],
4010 'disk' => [
4011 'enable' => (bool)$diskStatus,
4012 'external' => (bool)$diskExternalLinkStatus
4013 ],
4014 'path' => [
4015 'lf' => empty($arTemplate['PATH_TO_LF'])? '/': $arTemplate['PATH_TO_LF'],
4016 'profile' => empty($arTemplate['PATH_TO_USER_PROFILE'])? '': $arTemplate['PATH_TO_USER_PROFILE'],
4017 'profileTemplate' => empty($arTemplate['PATH_TO_USER_PROFILE_TEMPLATE'])? '': $arTemplate['PATH_TO_USER_PROFILE_TEMPLATE'],
4018 'mail' => empty($arTemplate['PATH_TO_USER_MAIL'])? '': $arTemplate['PATH_TO_USER_MAIL'],
4019 'crm' => $crmPath
4020 ]
4021 ];
4022
4023 return $initConfig;
4024 }
4025
4026 public static function StartWriting($dialogId, $userId = false, $userName = "", $byEvent = false, $linesSilentMode = false)
4027 {
4028 $userId = intval($userId);
4029 if ($userId <= 0)
4030 {
4031 global $USER;
4032 $userId = intval($USER->GetID());
4033 }
4034
4035 if (mb_substr($dialogId, 0, 4) == 'chat')
4036 {
4037 }
4038 else if ($dialogId == $userId)
4039 {
4040 return false;
4041 }
4042 else
4043 {
4044 $dialogId = intval($dialogId);
4045 }
4046
4047 $chatId = \Bitrix\Im\Dialog::getChatId($dialogId, $userId);
4048 $chat = Chat::getInstance($chatId);
4049
4050 if ($chat instanceof \Bitrix\Im\V2\Chat\NullChat)
4051 {
4052 return false;
4053 }
4054
4055 $action = new \Bitrix\Im\V2\Chat\InputAction\Action($chat, \Bitrix\Im\V2\Chat\InputAction\Type::Writing);
4056 $action = $action->withContextUser($userId);
4057 $action->setCustomUserName($userName);
4058 $action->setByEvent($byEvent);
4059 $action->setLinesSilentMode($linesSilentMode);
4060
4061 $result = $action->notify();
4062
4063 return $result->isSuccess();
4064 }
4065
4066 public static function PrepareSmiles()
4067 {
4068 return CSmileGallery::getSmilesWithSets();
4069 }
4070
4071 private static function UploadFileFromText($params)
4072 {
4073 $params['CHAT_ID'] = intval($params['CHAT_ID']);
4074 if (empty($params['MESSAGE']) || $params['CHAT_ID'] <= 0)
4075 {
4076 return $params;
4077 }
4078
4079 if (preg_match_all("/\[DISK=([0-9]+)\]/i", $params['MESSAGE'], $matches))
4080 {
4081 $fileFound = false;
4082 $files = [];
4083 foreach ($matches[1] as $fileId)
4084 {
4085 $newFile = CIMDisk::SaveFromLocalDisk($params['CHAT_ID'], $fileId, false, \Bitrix\Im\Common::getUserId());
4086 if ($newFile)
4087 {
4088 $files[] = $newFile;
4089 $fileFound = true;
4090 $params['PARAMS']['FILE_ID'][] = $newFile->getId();
4091 }
4092 }
4093 if ($fileFound)
4094 {
4095 $params['MESSAGE'] = preg_replace("/\[DISK\=([0-9]+)\]/i", "", $params['MESSAGE']);
4096 $params['FILES_FROM_TEXT'] = $files;
4097 }
4098 }
4099
4100 return $params;
4101 }
4102
4103 public static function SendMention($params)
4104 {
4105 $params['CHAT_ID'] = intval($params['CHAT_ID']);
4106 if (!isset($params['MESSAGE']) || $params['CHAT_ID'] <= 0)
4107 {
4108 return false;
4109 }
4110
4111 $userName = \Bitrix\Im\User::getInstance($params['FROM_USER_ID'])->getFullName(false);
4112 $userGender = \Bitrix\Im\User::getInstance($params['FROM_USER_ID'])->getGender();
4113
4114 if (!$userName)
4115 {
4116 return false;
4117 }
4118
4119 $chat = Chat::getInstance($params['CHAT_ID']);
4120 if ($chat instanceof \Bitrix\Im\V2\Chat\NullChat)
4121 {
4122 return false;
4123 }
4124
4125 $mentionUsers = $params['MENTION_USERS'] ?? self::getMentionUsers($params['MESSAGE']);
4126 if ($chat instanceof \Bitrix\Im\V2\Chat\CommentChat)
4127 {
4128 $parentChat = $chat->getParentChat();
4129 return self::SendMention([
4130 'CHAT_ID' => $parentChat->getId(),
4131 'PARENT_MID' => $chat->getParentMessageId(),
4132 'CHAT_TITLE' => htmlspecialcharsbx(Text::decodeEmoji($parentChat->getTitle())),
4133 'CHAT_RELATION' => self::getChatRelationForMention($parentChat, $mentionUsers),
4134 'CHAT_TYPE' => $parentChat->getType(),
4135 'CHAT_ENTITY_TYPE' => $parentChat->getEntityType(),
4136 'CHAT_COLOR' => $parentChat->getColor(),
4137 'MESSAGE' => $params['MESSAGE'],
4138 'FILES' => $params['FILES'],
4139 'FROM_USER_ID' => $params['FROM_USER_ID'],
4140 'MENTION_USERS' => $mentionUsers,
4141 ]);
4142 }
4143
4144 $params['CHAT_TITLE'] = $chat->getTitle() ?? '';
4145 $params['CHAT_TYPE'] = trim($chat->getType() ?? '');
4146 $params['CHAT_COLOR'] = trim($chat->getColor() ?? '');
4147 $params['CHAT_ENTITY_TYPE'] = trim($chat->getEntityType() ?? '');
4148 $params['CHAT_AVATAR'] = intval($chat->getAvatarId());
4149
4150 if (!in_array($params['CHAT_TYPE'], CIMChat::getGroupTypes()))
4151 {
4152 return false;
4153 }
4154
4155 if (!isset($params['CHAT_RELATION']))
4156 {
4157 $params['CHAT_RELATION'] = CIMChat::GetRelationById($params['CHAT_ID'], false, true, false);
4158 }
4159
4160 $forUsers = self::prepareUsersForMention($mentionUsers, $params);
4161
4162 $chatTitle = mb_substr(htmlspecialcharsback($params['CHAT_TITLE']), 0, 32);
4163 $pushText = GetMessage('IM_MESSAGE_MENTION_PUSH_2_'.($userGender=='F'?'F':'M'), Array('#USER#' => $userName, '#TITLE#' => $chatTitle)).': '.self::PrepareParamsForPush(Array('MESSAGE' => $params['MESSAGE'], 'FILES' => $params['FILES']));
4164
4165 $titleWithContext = '[CHAT='.$params['CHAT_ID'].']'.$chatTitle.'[/CHAT]';
4166 $commentModifier = '';
4167 $fromComment = false;
4168 if (isset($params['PARENT_MID']) && $params['PARENT_MID'])
4169 {
4170 $fromComment = true;
4171 $commentModifier = '_COMMENT';
4172 $titleWithContext = "[CONTEXT=chat{$params['CHAT_ID']}/{$params['PARENT_MID']}]{$chatTitle}[/CONTEXT]";
4173 }
4174
4175 $notifyMailCallback = fn (?string $languageId = null) => Loc::getMessage(
4176 "IM_MESSAGE_MENTION{$commentModifier}_".($userGender=='F'?'F':'M'),
4177 ['#TITLE#' => $chatTitle],
4178 $languageId
4179 );
4180 $notifyTextCallback = fn (?string $languageId = null) => Loc::getMessage(
4181 "IM_MESSAGE_MENTION{$commentModifier}_".($userGender=='F'?'F':'M'),
4182 ['#TITLE#' => $titleWithContext],
4183 $languageId
4184 );
4185
4186 if ($pushText <> '')
4187 {
4188 foreach ($forUsers as $userId)
4189 {
4190 if ($params['FROM_USER_ID'] == $userId)
4191 continue;
4192
4193 if($fromComment || self::shouldSendMentionNotification($params, $userId))
4194 {
4195 $arMessageFields = array(
4196 "TO_USER_ID" => $userId,
4197 "FROM_USER_ID" => $params['FROM_USER_ID'],
4198 "NOTIFY_TYPE" => IM_NOTIFY_FROM,
4199 "NOTIFY_MODULE" => "im",
4200 "NOTIFY_EVENT" => "mention",
4201 "NOTIFY_TAG" => 'IM|MENTION|'.$params['CHAT_ID'],
4202 "NOTIFY_SUB_TAG" => 'IM_MESS_'.$params['CHAT_ID'].'_'.$userId,
4203 'NOTIFY_MESSAGE' => $notifyTextCallback,
4204 'NOTIFY_MESSAGE_OUT' => $notifyMailCallback,
4205 );
4206 CIMNotify::Add($arMessageFields);
4207 }
4208
4209 if (!$fromComment)
4210 {
4211 \Bitrix\Pull\Push::add($userId, self::PreparePushForMentionInChat(Array(
4212 'CHAT_ID' => $params['CHAT_ID'],
4213 'CHAT_TITLE' => $params['CHAT_TITLE'],
4214 'CHAT_TYPE' => $params['CHAT_TYPE'],
4215 'CHAT_AVATAR' => $params['CHAT_AVATAR'],
4216 'CHAT_ENTITY_TYPE' => $params['CHAT_ENTITY_TYPE'],
4217 'FROM_USER_ID' => $params['FROM_USER_ID'],
4218 'MESSAGE' => $pushText,
4219 )));
4220 }
4221 }
4222 }
4223 return true;
4224 }
4225
4226 private static function shouldSendMentionNotification(array $params, int $userId): bool
4227 {
4228 $chatType = $params['CHAT_TYPE'];
4229 $isChatTypeCorrect = in_array($chatType, [Chat::IM_TYPE_OPEN_CHANNEL, Chat::IM_TYPE_OPEN], true);
4230
4231 $isUserInChat = isset($params['CHAT_RELATION'][$userId]);
4232
4233 return $isChatTypeCorrect && !$isUserInChat;
4234 }
4235
4236 private static function prepareUsersForMention(array $forUsers, $params): array
4237 {
4238 if (empty($forUsers))
4239 {
4240 return [];
4241 }
4242
4243 $usersForMention = [];
4244 foreach ($forUsers as $userId)
4245 {
4247 {
4248 continue;
4249 }
4250
4251 if ($params['CHAT_TYPE'] == IM_MESSAGE_OPEN || $params['CHAT_TYPE'] === Chat::IM_TYPE_OPEN_CHANNEL)
4252 {
4253 if (
4254 !isset($params['CHAT_RELATION'][$userId])
4255 || $params['CHAT_RELATION'][$userId]['NOTIFY_BLOCK'] == 'Y'
4256 )
4257 {
4258 $usersForMention[$userId] = $userId;
4259 }
4260 }
4261 else
4262 {
4263 if (
4264 isset($params['CHAT_RELATION'][$userId])
4265 && $params['CHAT_RELATION'][$userId]['NOTIFY_BLOCK'] == 'Y'
4266 )
4267 {
4268 $usersForMention[$userId] = $userId;
4269 }
4270 }
4271 }
4272
4273 return $usersForMention;
4274 }
4275
4276 private static function getMentionUsers(string $message): array
4277 {
4278 $forUsers = [];
4279 if (preg_match_all("/\[USER=([0-9]+)( REPLACE)?](.*?)\[\/USER]/i", $message, $matches))
4280 {
4281 foreach ($matches[1] as $userId)
4282 {
4283 $forUsers[(int)$userId] = (int)$userId;
4284 }
4285 }
4286
4287 return $forUsers;
4288 }
4289
4290 public static function PrepareParamsForPull($params)
4291 {
4292 if (!is_array($params))
4293 {
4294 return $params;
4295 }
4296
4297 foreach ($params as $key => $value)
4298 {
4299 if ($key == 'ATTACH')
4300 {
4301 if (is_object($value) && $value instanceof CIMMessageParamAttach)
4302 {
4303 $params[$key] = CIMMessageParamAttach::PrepareAttach($value->GetArray());
4304 }
4305 else
4306 {
4307 foreach ($value as $key2 => $value2)
4308 {
4309 if (is_object($value2) && $value2 instanceof CIMMessageParamAttach)
4310 {
4311 $params[$key][$key2] = CIMMessageParamAttach::PrepareAttach($value2->GetArray());
4312 }
4313 }
4314 }
4315 }
4316 elseif ($key == 'KEYBOARD')
4317 {
4318 if (is_object($value) && $value instanceof \Bitrix\Im\Bot\Keyboard)
4319 {
4320 $params[$key] = $value->getArray();
4321 }
4322 }
4323 elseif ($key == 'MENU')
4324 {
4325 if (is_object($value) && $value instanceof \Bitrix\Im\Bot\ContextMenu)
4326 {
4327 $params[$key] = $value->getArray();
4328 }
4329 }
4330 elseif ($key == 'AVATAR' && intval($value) > 0)
4331 {
4332 $params[$key] = CIMChat::GetAvatarImage($value, 200, false);
4333 }
4334 elseif ($key === 'COMPONENT_PARAMS')
4335 {
4336 $params[$key] = Converter::toJson()->process(self::decodeEmoji($value));
4337 }
4338 }
4339
4340 return $params;
4341 }
4342
4343 protected static function decodeEmoji($value)
4344 {
4345 if (is_string($value))
4346 {
4347 $value = Emoji::decode($value);
4348 }
4349
4350 if (is_array($value))
4351 {
4352 foreach ($value as $key => $item)
4353 {
4354 $value[$key] = self::decodeEmoji($item);
4355 }
4356 }
4357
4358 return $value;
4359 }
4360
4361 public static function PreparePushForMentionInChat($params)
4362 {
4363 $params['CHAT_ID'] = intval($params['CHAT_ID']);
4364 if ($params['CHAT_ID'] <= 0)
4365 {
4366 return false;
4367 }
4368
4369 $params['CHAT_TITLE'] = mb_substr(htmlspecialcharsback($params['CHAT_TITLE']), 0, 32);
4370
4371 $pushText = $params['MESSAGE'];
4372
4373 $chatType = \Bitrix\Im\Chat::getType($params);
4374
4375 $avatarUser = \Bitrix\Im\User::getInstance($params['FROM_USER_ID'])->getAvatar();
4376 if ($avatarUser && mb_strpos($avatarUser, 'http') !== 0)
4377 {
4378 $avatarUser = \Bitrix\Im\Common::getPublicDomain().$avatarUser;
4379 }
4380
4381 $avatarChat = \CIMChat::GetAvatarImage($params['CHAT_AVATAR'], 200, false);
4382 if ($avatarChat && mb_strpos($avatarChat, 'http') !== 0)
4383 {
4384 $avatarChat = \Bitrix\Im\Common::getPublicDomain().$avatarChat;
4385 }
4386
4387 $result = Array();
4388 $result['module_id'] = 'im';
4389 $result['push']['params'] = Array(
4390 'TAG' => 'IM_CHAT_'.$params['CHAT_ID'],
4391 'CHAT_TYPE' => $params['CHAT_TYPE'],
4392 'CATEGORY' => 'ANSWER',
4393 'URL' => SITE_DIR.'mobile/ajax.php?mobile_action=im_answer',
4394 'PARAMS' => Array(
4395 'RECIPIENT_ID' => 'chat'.$params['CHAT_ID']
4396 )
4397 );
4398 $result['push']['type'] = $params['PUSH_TYPE']? $params['PUSH_TYPE']: ($params['CHAT_TYPE'] == IM_MESSAGE_OPEN? 'openChat': 'chat');
4399 $result['push']['tag'] = 'IM_CHAT_'.$params['CHAT_ID'];
4400 $result['push']['sub_tag'] = 'IM_MESS';
4401 $result['push']['app_id'] = 'Bitrix24';
4402 $result['push']['message'] = $pushText;
4403 $result['push']['advanced_params'] = array(
4404 "group"=> $chatType == 'lines'? 'im_lines_message': 'im_message',
4405 "avatarUrl"=> $avatarChat? $avatarChat: $avatarUser,
4406 "senderName" => (string)$params['CHAT_TITLE'],
4407 "senderMessage" => $pushText,
4408 );
4409
4410 return $result;
4411 }
4412
4413 public static function PreparePushForChat($params)
4414 {
4415 $attachmentSuffix = MobilePush::getAttachmentSuffixForPush($params['params']);
4416 $pushText = self::PrepareMessageForPush($params['params']);
4417 unset($params['params']['message']['text_push']);
4418
4419 $chatTitle = mb_substr(htmlspecialcharsback($params['params']['chat'][$params['params']['chatId']]['name']), 0, 32);
4420 $chatType = $params['params']['chat'][$params['params']['chatId']]['type'];
4421 $chatAvatar = $params['params']['chat'][$params['params']['chatId']]['avatar'];
4422 $chatTypeLetter = $params['params']['chat'][$params['params']['chatId']]['message_type'];
4423
4424
4425 if (($params['params']['system'] ?? null) === 'Y' || $params['params']['message']['senderId'] <= 0)
4426 {
4427 $avatarUser = '';
4428 $userName = '';
4429 }
4430 else
4431 {
4432 $userName = \Bitrix\Im\User::getInstance($params['params']['message']['senderId'])->getFullName(false);
4433 $avatarUser = \Bitrix\Im\User::getInstance($params['params']['message']['senderId'])->getAvatar();
4434 if ($avatarUser && mb_strpos($avatarUser, 'http') !== 0)
4435 {
4436 $avatarUser = \Bitrix\Im\Common::getPublicDomain().$avatarUser;
4437 }
4438 }
4439
4440 if (
4441 isset(
4442 $params['params']['message']['senderId'],
4443 $params['params']['users'][$params['params']['message']['senderId']]
4444 )
4445 && $params['params']['users'][$params['params']['message']['senderId']]
4446 )
4447 {
4448 $params['params']['users'] = [
4449 $params['params']['message']['senderId'] => $params['params']['users'][$params['params']['message']['senderId']]
4450 ];
4451 }
4452 else
4453 {
4454 $params['params']['users'] = [];
4455 }
4456
4457 if ($chatAvatar == '/bitrix/js/im/images/blank.gif')
4458 {
4459 $chatAvatar = '';
4460 }
4461 else if ($chatAvatar && mb_strpos($chatAvatar, 'http') !== 0)
4462 {
4463 $chatAvatar = \Bitrix\Im\Common::getPublicDomain().$chatAvatar;
4464 }
4465
4466 unset($params['extra']);
4467
4468 array_walk_recursive($params, function(&$item, $key)
4469 {
4470 if (is_null($item))
4471 {
4472 $item = false;
4473 }
4474 else if ($item instanceof \Bitrix\Main\Type\DateTime)
4475 {
4476 $item = date('c', $item->getTimestamp());
4477 }
4478 });
4479
4480 $result = Array();
4481 $result['module_id'] = 'im';
4482 $result['push']['type'] = ($chatType === 'open'? 'openChat': $chatType);
4483 $result['push']['tag'] = 'IM_CHAT_'.intval($params['params']['chatId']);
4484 $result['push']['sub_tag'] = 'IM_MESS';
4485 $result['push']['app_id'] = 'Bitrix24';
4486 $result['push']['message'] = ($userName? $userName.': ': '').$pushText;
4487 $result['push']['advanced_params'] = array(
4488 "group"=> $chatType == 'lines'? 'im_lines_message': 'im_message',
4489 "avatarUrl"=> $chatAvatar? $chatAvatar: $avatarUser,
4490 "senderName" => $chatTitle,
4491 "senderMessage" => ($userName? $userName.': ': '').$pushText,
4492 'attachmentSuffix' => $attachmentSuffix,
4493 "senderCut" => mb_strlen($userName? $userName.': ' : ''),
4494 "data" => self::PrepareEventForPush($params['command'], $params['params'])
4495 );
4496 $result['push']['params'] = Array(
4497 'TAG' => 'IM_CHAT_'.$params['params']['chatId'],
4498 'CHAT_TYPE' => $chatTypeLetter? $chatTypeLetter: 'C',
4499 'CATEGORY' => 'ANSWER',
4500 'URL' => SITE_DIR.'mobile/ajax.php?mobile_action=im_answer',
4501 'PARAMS' => Array(
4502 'RECIPIENT_ID' => 'chat'.$params['params']['chatId'],
4503 'MESSAGE_ID' => $params['params']['message']['id']
4504 ),
4505 );
4506
4507 return $result;
4508 }
4509
4510 public static function PreparePushForPrivate($params)
4511 {
4512 $attachmentSuffix = MobilePush::getAttachmentSuffixForPush($params['params']);
4513 $pushText = self::PrepareMessageForPush($params['params']);
4514 unset($params['params']['message']['text_push']);
4515
4516 if (isset($params['params']['system']) && $params['params']['system'] == 'Y')
4517 {
4518 $userName = '';
4519 $avatarUser = '';
4520 }
4521 else
4522 {
4523 $userName = \Bitrix\Im\User::getInstance($params['params']['message']['senderId'])->getFullName(false);
4524 $avatarUser = \Bitrix\Im\User::getInstance($params['params']['message']['senderId'])->getAvatar();
4525 if ($avatarUser && mb_strpos($avatarUser, 'http') !== 0)
4526 {
4527 $avatarUser = \Bitrix\Im\Common::getPublicDomain().$avatarUser;
4528 }
4529 }
4530
4531 if ($params['params']['users'][$params['params']['message']['senderId']])
4532 {
4533 $params['params']['users'] = Array(
4534 $params['params']['message']['senderId'] => $params['params']['users'][$params['params']['message']['senderId']]
4535 );
4536 }
4537 else
4538 {
4539 $params['params']['users'] = Array();
4540 }
4541
4542 unset($params['extra']);
4543
4544 array_walk_recursive($params, function(&$item, $key)
4545 {
4546 if (is_null($item))
4547 {
4548 $item = false;
4549 }
4550 else if ($item instanceof \Bitrix\Main\Type\DateTime)
4551 {
4552 $item = date('c', $item->getTimestamp());
4553 }
4554 });
4555
4556 $result = Array();
4557 $result['module_id'] = 'im';
4558 $result['push']['type'] = 'message';
4559 $result['push']['tag'] = 'IM_MESS_'.intval($params['params']['message']['senderId']);
4560 $result['push']['sub_tag'] = 'IM_MESS';
4561 $result['push']['app_id'] = 'Bitrix24';
4562 $result['push']['message'] = $pushText;
4563 $result['push']['advanced_params'] = array(
4564 "group"=> 'im_message',
4565 "avatarUrl"=> $avatarUser,
4566 "senderName" => $userName,
4567 "senderMessage" => $pushText,
4568 'attachmentSuffix' => $attachmentSuffix,
4569 "data" => self::PrepareEventForPush($params['command'], $params['params']),
4570 );
4571 $result['push']['params'] = Array(
4572 'TAG' => 'IM_MESS_'.$params['params']['message']['senderId'],
4573 'CATEGORY' => 'ANSWER',
4574 'URL' => SITE_DIR.'mobile/ajax.php?mobile_action=im_answer',
4575 'PARAMS' => Array(
4576 'RECIPIENT_ID' => (int)$params['params']['message']['senderId'],
4577 'MESSAGE_ID' => $params['params']['message']['id']
4578 ),
4579 );
4580
4581 return $result;
4582 }
4583
4584 private static function prepareAdvancedParamsForNotificationPush(array $params, string $pushMessage = null): array
4585 {
4586 if ($params['date'] instanceof \Bitrix\Main\Type\DateTime)
4587 {
4588 $params['date'] = date('c', $params['date']->getTimestamp());
4589 }
4590
4591 $params['text'] = self::PrepareMessageForPush(['message' => ['text' => $params['text']]]);
4592
4593 $advancedParams = [
4594 'id' => 'im_notify',
4595 'group' => 'im_notify',
4596 'data' => self::prepareNotificationEventForPush($params, $pushMessage)
4597 ];
4598
4599 if (isset($params['userName']))
4600 {
4601 $advancedParams['senderName'] = $params['userName'];
4602 if (isset($params['userAvatar']))
4603 {
4604 $advancedParams['avatarUrl'] = $params['userAvatar'];
4605 }
4606 $advancedParams['senderMessage'] = $pushMessage ?: $params['text'];
4607 }
4608
4609 return $advancedParams;
4610 }
4611
4612 public static function PrepareParamsForPush($params)
4613 {
4614 if (!isset($params['MESSAGE']))
4615 {
4616 $params['MESSAGE'] = '';
4617 }
4618 $params['MESSAGE'] = trim($params['MESSAGE']);
4619
4620 $pushFiles = '';
4621 if (isset($params['FILES']) && count($params['FILES']) > 0)
4622 {
4623 foreach ($params['FILES'] as $file)
4624 {
4625 $pushFiles .= " [".GetMessage('IM_MESSAGE_FILE').": ".$file['name']."]";
4626 }
4627 $params['MESSAGE'] .= $pushFiles;
4628 }
4629
4630 $hasAttach = mb_strpos($params['MESSAGE'], '[ATTACH=') !== false;
4631
4632 $params['MESSAGE'] = preg_replace("/\[CODE\](.*?)\[\/CODE\]/si", " [".GetMessage('IM_MESSAGE_CODE')."] ", $params['MESSAGE']);
4633 $params['MESSAGE'] = preg_replace("/\[s]([^[]*(?:\[(?!s]|\/s])[^[]*)*)\[\/s]/i", "-", $params['MESSAGE']);
4634 $params['MESSAGE'] = preg_replace("/\[b]([^[]*(?:\[(?!b]|\/b])[^[]*)*)\[\/b]/i", "$1", $params['MESSAGE']);
4635 $params['MESSAGE'] = preg_replace("/\[i]([^[]*(?:\[(?!i]|\/i])[^[]*)*)\[\/i]/i", "$1", $params['MESSAGE']);
4636 $params['MESSAGE'] = preg_replace("/\[u]([^[]*(?:\[(?!u]|\/u])[^[]*)*)\[\/u]/i", "$1", $params['MESSAGE']);
4637 $params['MESSAGE'] = preg_replace("/\\[url\\](.*?)\\[\\/url\\]/iu", "$1", $params['MESSAGE']);
4638 $params['MESSAGE'] = preg_replace("/\\[url\\s*=\\s*((?:[^\\[\\]]++|\\[ (?: (?>[^\\[\\]]+) | (?:\\1) )* \\])+)\\s*\\](.*?)\\[\\/url\\]/ixsu", "$2", $params['MESSAGE']);
4639 $params['MESSAGE'] = preg_replace_callback("/\[USER=([0-9]{1,})\]\[\/USER\]/i", Array('\Bitrix\Im\Text', 'modifyShortUserTag'), $params['MESSAGE']);
4640 $params['MESSAGE'] = preg_replace("/\[USER=([0-9]+)( REPLACE)?](.+?)\[\/USER]/i", "$3", $params['MESSAGE']);
4641 $params['MESSAGE'] = preg_replace("/\[CHAT=([0-9]{1,})\](.*?)\[\/CHAT\]/i", "$2", $params['MESSAGE']);
4642 $params['MESSAGE'] = preg_replace_callback("/\[SEND(?:=(?:.+?))?\](?:.+?)?\[\/SEND]/i", Array("CIMMessenger", "PrepareMessageForPushSendPutCallBack"), $params['MESSAGE']);
4643 $params['MESSAGE'] = preg_replace_callback("/\[PUT(?:=(?:.+?))?\](?:.+?)?\[\/PUT]/i", Array("CIMMessenger", "PrepareMessageForPushSendPutCallBack"), $params['MESSAGE']);
4644 $params['MESSAGE'] = preg_replace("/\[CALL(?:=(.+?))?\](.+?)?\[\/CALL\]/i", "$2", $params['MESSAGE']);
4645 $params['MESSAGE'] = preg_replace("/\[PCH=([0-9]{1,})\](.*?)\[\/PCH\]/i", "$2", $params['MESSAGE']);
4646 $params['MESSAGE'] = preg_replace_callback("/\[ICON\=([^\]]*)\]/i", Array("CIMMessenger", "PrepareMessageForPushIconCallBack"), $params['MESSAGE']);
4647 $params['MESSAGE'] = preg_replace_callback('/\[TIMESTAMP=(\d+) FORMAT=([^\]]*)\]/i', [Text::class, 'modifyTimestampCode'], $params['MESSAGE']);
4648 $params['MESSAGE'] = preg_replace('#\-{54}.+?\-{54}#s', " [".GetMessage('IM_QUOTE')."] ", str_replace(array("#BR#"), Array(" "), $params['MESSAGE']));
4649 $params['MESSAGE'] = preg_replace('/^(>>(.*)(\n)?)/mi', " [".GetMessage('IM_QUOTE')."] ", str_replace(array("#BR#"), Array(" "), $params['MESSAGE']));
4650
4651 if (!$pushFiles && !$hasAttach && ($params['ATTACH'] ?? null))
4652 {
4653 $params['MESSAGE'] .= " [".GetMessage('IM_MESSAGE_ATTACH')."]";
4654 }
4655
4656 return $params['MESSAGE'];
4657 }
4658
4659 public static function PrepareMessageForPush($message)
4660 {
4661 if (isset($message['message']['text_push']) && $message['message']['text_push'])
4662 {
4663 $message['message']['text'] = $message['message']['text_push'];
4664 }
4665 else
4666 {
4667 if (isset($message['message']['params']['ATTACH']) && count($message['message']['params']['ATTACH']) > 0)
4668 {
4669 $attachText = $message['message']['params']['ATTACH'][0]['DESCRIPTION'];
4670 if (!$attachText)
4671 {
4672 $attachText = Text::getEmoji('attach').' '.GetMessage('IM_MESSAGE_ATTACH');
4673 }
4674
4675 if ($attachText === \CIMMessageParamAttach::SKIP_MESSAGE)
4676 {
4677 $attachText = '';
4678 }
4679
4680 $message['message']['text'] .=
4681 (empty($message['message']['text'])? '': " ")
4682 .$attachText
4683 ;
4684 }
4685
4686 if (isset($message['files']) && count($message['files']) > 0)
4687 {
4688 $file = array_values($message['files'])[0];
4689
4690 if ($file['type'] === 'image')
4691 {
4692 $fileName = Text::getEmoji($file['type']).' '.GetMessage('IM_MESSAGE_IMAGE');
4693 }
4694 else if ($file['type'] === 'audio')
4695 {
4696 $fileName = Text::getEmoji($file['type']).' '.GetMessage('IM_MESSAGE_AUDIO');
4697 }
4698 else if ($file['type'] === 'video')
4699 {
4700 $fileName = Text::getEmoji($file['type']).' '.GetMessage('IM_MESSAGE_VIDEO');
4701 }
4702 else
4703 {
4704 $fileName = Text::getEmoji('file', GetMessage('IM_MESSAGE_FILE').":")." ".$file['name'];
4705 }
4706
4707 $message['message']['text'] .= trim($fileName);
4708 }
4709 }
4710
4711 $codeIcon = Text::getEmoji('code', "[".GetMessage('IM_MESSAGE_CODE')."]");
4712 $quoteIcon = Text::getEmoji('quote', "[".GetMessage('IM_QUOTE')."]");
4713
4714 $message['message']['text'] = str_replace("\n", " ", $message['message']['text']);
4715
4716 $message['message']['text'] = preg_replace("/\[CODE\](.*?)\[\/CODE\]/si", " ".$codeIcon." ", $message['message']['text']);
4717 $message['message']['text'] = preg_replace("/\[s\].*?\[\/s\]/i", "-", $message['message']['text']);
4718 $message['message']['text'] = preg_replace("/\[[bui]\](.*?)\[\/[bui]\]/i", "$1", $message['message']['text']);
4719 $message['message']['text'] = preg_replace("/\\[url\\](.*?)\\[\\/url\\]/iu", "$1", $message['message']['text']);
4720 $message['message']['text'] = preg_replace("/\\[url\\s*=\\s*((?:[^\\[\\]]++|\\[ (?: (?>[^\\[\\]]+) | (?:\\1) )* \\])+)\\s*\\](.*?)\\[\\/url\\]/ixsu", "$2", $message['message']['text']);
4721 $message['message']['text'] = preg_replace_callback("/\[USER=([0-9]{1,})\]\[\/USER\]/i", Array('\Bitrix\Im\Text', 'modifyShortUserTag'), $message['message']['text']);
4722 $message['message']['text'] = preg_replace("/\[USER=([0-9]+)( REPLACE)?](.+?)\[\/USER]/i", "$3", $message['message']['text']);
4723 $message['message']['text'] = preg_replace("/\[CHAT=([0-9]{1,})\](.*?)\[\/CHAT\]/i", "$2", $message['message']['text']);
4724 $message['message']['text'] = preg_replace("/\[context=(chat\d+|\d+:\d+)\/(\d+)](.*?)\[\/context]/i", "$3", $message['message']['text']);
4725 $message['message']['text'] = preg_replace_callback("/\[SEND(?:=(?:.+?))?\](?:.+?)?\[\/SEND]/i", Array("CIMMessenger", "PrepareMessageForPushSendPutCallBack"), $message['message']['text']);
4726 $message['message']['text'] = preg_replace_callback("/\[PUT(?:=(?:.+?))?\](?:.+?)?\[\/PUT]/i", Array("CIMMessenger", "PrepareMessageForPushSendPutCallBack"), $message['message']['text']);
4727 $message['message']['text'] = preg_replace("/\[CALL(?:=(.+?))?\](.+?)?\[\/CALL\]/i", "$2", $message['message']['text']);
4728 $message['message']['text'] = preg_replace("/\[PCH=([0-9]{1,})\](.*?)\[\/PCH\]/i", "$2", $message['message']['text']);
4729 $message['message']['text'] = preg_replace_callback("/\[ICON\=([^\]]*)\]/i", Array("CIMMessenger", "PrepareMessageForPushIconCallBack"), $message['message']['text']);
4730 $message['message']['text'] = preg_replace_callback('/\[TIMESTAMP=(\d+) FORMAT=([^\]]*)\]/i', [Text::class, 'modifyTimestampCode'], $message['message']['text']);
4731 $message['message']['text'] = preg_replace('#\-{54}.+?\-{54}#s', " ".$quoteIcon." ", str_replace(array("#BR#"), Array(" "), $message['message']['text']));
4732 $message['message']['text'] = preg_replace('/^(>>(.*)(\n)?)/mi', " ".$quoteIcon." ", str_replace(array("#BR#"), Array(" "), $message['message']['text']));
4733 $message['message']['text'] = preg_replace("/\\[color\\s*=\\s*([^\\]]+)\\](.*?)\\[\\/color\\]/isu", "$2", $message['message']['text']);
4734 $message['message']['text'] = preg_replace("/\\[size\\s*=\\s*([^\\]]+)\\](.*?)\\[\\/size\\]/isu", "$2", $message['message']['text']);
4735
4736 return trim($message['message']['text']);
4737 }
4738
4739 public static function PrepareEventForPush($command, $event)
4740 {
4741 $result = [
4742 'cmd' => (string)$command,
4743 'chatId' => (int)$event['chatId'],
4744 'dialogId' => (string)$event['dialogId'],
4745 'counter' => (int)$event['counter'],
4746 ];
4747
4748 if ($event['notify'] !== true)
4749 {
4750 $result['notify'] = $event['notify'];
4751 }
4752
4753 if (!empty($event['chat'][$event['chatId']]))
4754 {
4755 $eventChat = $event['chat'][$event['chatId']];
4756
4757 $chat = [
4758 'id' => (int)$eventChat['id'],
4759 'name' => (string)$eventChat['name'],
4760 'owner' => (int)$eventChat['owner'],
4761 'color' => (string)$eventChat['color'],
4762 'type' => (string)$eventChat['type'],
4763 'date_create' => (string)$eventChat['date_create'],
4764 ];
4765
4766 if (
4767 !empty($eventChat['avatar'])
4768 && $eventChat['avatar'] !== '/bitrix/js/im/images/blank.gif'
4769 )
4770 {
4771 $chat['avatar'] = $eventChat['avatar'];
4772 }
4773 if ($eventChat['call'])
4774 {
4775 $chat['call'] = (string)$eventChat['call'];
4776 }
4777 if ($eventChat['call_number'])
4778 {
4779 $chat['call_number'] = (string)$eventChat['call_number'];
4780 }
4781 if ($eventChat['entity_data_1'])
4782 {
4783 $chat['entity_data_1'] = (string)$eventChat['entity_data_1'];
4784 }
4785 if ($eventChat['entity_data_2'])
4786 {
4787 $chat['entity_data_2'] = (string)$eventChat['entity_data_2'];
4788 }
4789 if ($eventChat['entity_data_3'])
4790 {
4791 $chat['entity_data_3'] = (string)$eventChat['entity_data_3'];
4792 }
4793 if ($eventChat['entity_id'])
4794 {
4795 $chat['entity_id'] = (string)$eventChat['entity_id'];
4796 }
4797 if ($eventChat['entity_type'])
4798 {
4799 $chat['entity_type'] = (string)$eventChat['entity_type'];
4800 }
4801 if ($eventChat['extranet'])
4802 {
4803 $chat['extranet'] = true;
4804 }
4805
4806 $result['chat'] = $chat;
4807 }
4808
4809 if (!empty($event['lines']))
4810 {
4811 $result['lines'] = $event['lines'];
4812 }
4813
4814 if (!empty($event['users'][$event['message']['senderId']]))
4815 {
4816 $eventUser = $event['users'][$event['message']['senderId']];
4817
4818 $user = [
4819 'id' => (int)$eventUser['id'],
4820 'name' => (string)$eventUser['name'],
4821 'first_name' => (string)$eventUser['first_name'],
4822 'last_name' => (string)$eventUser['last_name'],
4823 'color' => (string)$eventUser['color'],
4824 ];
4825
4826 if (
4827 !empty($eventUser['avatar'])
4828 && $eventUser['avatar'] !== '/bitrix/js/im/images/blank.gif'
4829 )
4830 {
4831 $user['avatar'] = (string)$eventUser['avatar'];
4832 }
4833
4834 if ($eventUser['absent'])
4835 {
4836 $user['absent'] = true;
4837 }
4838 if (!$eventUser['active'])
4839 {
4840 $user['active'] = $eventUser['active'];
4841 }
4842 if ($eventUser['bot'])
4843 {
4844 $user['bot'] = true;
4845 }
4846 if ($eventUser['extranet'])
4847 {
4848 $user['extranet'] = true;
4849 }
4850 if ($eventUser['network'])
4851 {
4852 $user['network'] = true;
4853 }
4854 if ($eventUser['birthday'])
4855 {
4856 $user['birthday'] = $eventUser['birthday'];
4857 }
4858 if ($eventUser['connector'])
4859 {
4860 $user['connector'] = true;
4861 }
4862 if ($eventUser['external_auth_id'] !== 'default')
4863 {
4864 $user['external_auth_id'] = $eventUser['external_auth_id'];
4865 }
4866 if ($eventUser['gender'] === 'F')
4867 {
4868 $user['gender'] = 'F';
4869 }
4870 if ($eventUser['work_position'])
4871 {
4872 $user['work_position'] = (string)$eventUser['work_position'];
4873 }
4874
4875 $result['users'] = $user;
4876 }
4877
4878 if (!empty($event['files']))
4879 {
4880 foreach ($event['files'] as $key => $value)
4881 {
4882 $file = [
4883 'id' => (int)$value['id'],
4884 'extension' => (string)$value['extension'],
4885 'name' => (string)$value['name'],
4886 'size' => (int)$value['size'],
4887 'type' => (string)$value['type'],
4888 'image' => $value['image'],
4889 'urlDownload' => '',
4890 'urlPreview' => (new Uri($value['urlPreview']))->deleteParams(['fileName'])->getUri(),
4891 'urlShow' => (new Uri($value['urlShow']))->deleteParams(['fileName'])->getUri(),
4892 ];
4893 if ($value['image'])
4894 {
4895 $file['image'] = $value['image'];
4896 }
4897 if ($value['progress'] !== 100)
4898 {
4899 $file['progress'] = (int)$value['progress'];
4900 }
4901 if ($value['status'] !== 'done')
4902 {
4903 $file['status'] = $value['status'];
4904 }
4905
4906 $result['files'][$key] = $file;
4907 }
4908 }
4909
4910 if (!empty($event['message']))
4911 {
4912 $eventMessage = $event['message'];
4913
4914 $message = [
4915 'id' => (int)$eventMessage['id'],
4916 'date' => (string)$eventMessage['date'],
4917 'params' => $eventMessage['params'],
4918 'prevId' => (int)$eventMessage['prevId'],
4919 'senderId' => (int)$eventMessage['senderId'],
4920 ];
4921
4922 if (isset($message['params']['ATTACH']))
4923 {
4924 unset($message['params']['ATTACH']);
4925 }
4926
4927 if ($eventMessage['system'] === 'Y')
4928 {
4929 $message['system'] = 'Y';
4930 }
4931
4932 $result['message'] = $message;
4933 }
4934
4935 $indexToNameMap = [
4936 "chat" => 1,
4937 "chatId" => 2,
4938 "counter" => 3,
4939 "dialogId" => 4,
4940 "files" => 5,
4941 "message" => 6,
4942 "users" => 8,
4943 "name" => 9,
4944 "avatar" => 10,
4945 "color" => 11,
4946 "notify" => 12,
4947 "type" => 13,
4948 "extranet" => 14,
4949
4950 "date_create" => 20,
4951 "owner" => 21,
4952 "entity_id" => 23,
4953 "entity_type" => 24,
4954 "entity_data_1" => 203,
4955 "entity_data_2" => 204,
4956 "entity_data_3" => 205,
4957 "call" => 201,
4958 "call_number" => 202,
4959 "manager_list" => 209,
4960 "mute_list" => 210,
4961
4962 "first_name" => 40,
4963 "last_name" => 41,
4964 "gender" => 42,
4965 "work_position" => 43,
4966 "active" => 400,
4967 "birthday" => 401,
4968 "bot" => 402,
4969 "connector" => 403,
4970 "external_auth_id" => 404,
4971 "network" => 406,
4972
4973
4974 "textLegacy" => 65,
4975 "date" => 61,
4976 "prevId" => 62,
4977 "params" => 63,
4978 "senderId" => 64,
4979 "system" => 601,
4980
4981 "extension" => 80,
4982 "image" => 81,
4983 "progress" => 82,
4984 "size" => 83,
4985 "status" => 84,
4986 "urlDownload" => 85,
4987 "urlPreview" => 86,
4988 "urlShow" => 87,
4989 "width" => 88,
4990 "height" => 89,
4991 ];
4992
4993 return self::PrepareEventForPushChangeKeys($result, $indexToNameMap);
4994 }
4995
5005 private static function prepareNotificationEventForPush(array $event, string $pushMessage = null): array
5006 {
5007 $result = [
5008 'cmd' => 'notifyAdd',
5009 'id' => (int)$event['id'],
5010 'type' => (int)$event['type'],
5011 'date' => (string)$event['date'],
5012 'tag' => (string)$event['tag'],
5013 'onlyFlash' => $event['onlyFlash'],
5014 'originalTag' => (string)$event['originalTag'],
5015 'settingName' => (string)$event['settingName'],
5016 'counter' => (int)$event['counter'],
5017 'userId' => (int)$event['userId'],
5018 'userName' => (string)$event['userName'],
5019 'userColor' => (string)$event['userColor'],
5020 'userAvatar' => (string)$event['userAvatar'],
5021 'userLink' => (string)$event['userLink'],
5022 'params' => $event['params'],
5023 ];
5024 if (isset($event['buttons']))
5025 {
5026 $result['buttons'] = $event['buttons'];
5027 }
5028
5029 // We need to save original text ("long") in result only if we have push text ("short").
5030 // "Long" text will be used to render push in notifications list.
5031 if (isset($pushMessage))
5032 {
5033 $result['text'] = $event['text'];
5034 }
5035
5036 $fieldToIndex = [
5037 'id' => 1,
5038 'type' => 2,
5039 'date' => 3,
5040 'text' => 4,
5041 'tag' => 6,
5042 'onlyFlash' => 7,
5043 'originalTag' => 8,
5044 'settingName' => 9,
5045 'counter' => 10,
5046 'userId' => 11,
5047 'userName' => 12,
5048 'userColor' => 13,
5049 'userAvatar' => 14,
5050 'userLink' => 15,
5051 'params' => 16,
5052 'buttons' => 17,
5053 ];
5054
5055 return self::PrepareEventForPushChangeKeys($result, $fieldToIndex);
5056 }
5057
5058 private static function PrepareEventForPushChangeKeys($object, $map)
5059 {
5060 $result = [];
5061
5062 foreach($object as $key => $value)
5063 {
5064 $index = isset($map[$key])? $map[$key]: $key;
5065 if (is_null($value))
5066 {
5067 $value = "";
5068 }
5069 if (is_array($value))
5070 {
5071 $result[$index] = self::PrepareEventForPushChangeKeys($value, $map);
5072 }
5073 else
5074 {
5075 $result[$index] = $value;
5076 }
5077 }
5078
5079 return $result;
5080 }
5081
5082 private static function getFilesFromMessage(array $models, array $filesFromText, array $params): array
5083 {
5084 $allFiles = [];
5085 $filesToSelect = [];
5086
5087 foreach ([$models, $filesFromText] as $sourceModels)
5088 {
5089 foreach ($sourceModels as $model)
5090 {
5091 if ($model instanceof \Bitrix\Disk\File)
5092 {
5093 $allFiles[$model->getId()] = $model;
5094 }
5095 }
5096 }
5097
5098 foreach ($params['FILE_ID'] ?? [] as $fileId)
5099 {
5100 if (!isset($allFiles[$fileId]))
5101 {
5102 $filesToSelect[] = $fileId;
5103 }
5104 }
5105
5106 if (!empty($filesToSelect))
5107 {
5108 $selectedFiles = \Bitrix\Im\V2\Entity\File\FileCollection::initByDiskFilesIds($filesToSelect)
5109 ->getDiskFiles()
5110 ;
5111 $allFiles += $selectedFiles;
5112 }
5113
5114 return $allFiles;
5115 }
5116
5118 {
5119 $code = mb_strpos(mb_strtoupper($params[0]), '[SEND') === 0? 'SEND': 'PUT';
5120 return preg_replace("/\[$code(?:=(.+))?\](.+?)?\[\/$code\]/i", "$2", $params[0]);
5121 }
5122
5124 {
5125 $text = $params[1];
5126
5127 $title = GetMessage('IM_MESSAGE_ICON');
5128
5129 preg_match('/title\=(.*[^\s\]])/i', $text, $match);
5130 if ($match)
5131 {
5132 $title = $match[1];
5133 if (mb_strpos($title, 'width=') !== false)
5134 {
5135 $title = mb_substr($title, 0, mb_strpos($title, 'width='));
5136 }
5137 if (mb_strpos($title, 'height=') !== false)
5138 {
5139 $title = mb_substr($title, 0, mb_strpos($title, 'height='));
5140 }
5141 if (mb_strpos($title, 'size=') !== false)
5142 {
5143 $title = mb_substr($title, 0, mb_strpos($title, 'size='));
5144 }
5145 $title = trim($title);
5146 }
5147
5148 return '('.$title.')';
5149 }
5150
5151 /* TMP FUNCTION */
5152 public static function GetCachePath($id)
5153 {
5154 return \Bitrix\Im\Common::getCacheUserPostfix($id);
5155 }
5156
5157 function GetSonetCode($user_id, $site_id = SITE_ID)
5158 {
5159 global $DB;
5160 $result = array();
5161 $user_id = intval($user_id);
5162
5163 if($user_id > 0 && IsModuleInstalled('socialnetwork'))
5164 {
5165 $strSQL = "
5166 SELECT CODE, SUM(CNT) as CNT
5167 FROM b_sonet_log_counter
5168 WHERE USER_ID = ".$user_id."
5169 AND (SITE_ID = '".$site_id."' OR SITE_ID = '**')
5170 GROUP BY CODE
5171 ";
5172 $dbRes = $DB->Query($strSQL, true);
5173 while ($arRes = $dbRes->Fetch())
5174 $result[$arRes["CODE"]] = $arRes["CNT"];
5175 }
5176
5177 return $result;
5178 }
5179
5180 public static function EnableMessageCheck()
5181 {
5182 self::$enableMessageCheck++;
5183 return true;
5184 }
5185 public static function DisableMessageCheck()
5186 {
5187 self::$enableMessageCheck--;
5188 return true;
5189 }
5190
5191 public static function IsEnabledMessageCheck()
5192 {
5193 return self::$enableMessageCheck > 0;
5194 }
5195
5196 public static function IsBitrix24UserRestricted()
5197 {
5198 global $USER;
5199
5200 return (
5201 \Bitrix\Main\Loader::includeModule('bitrix24')
5202 && \Bitrix\Bitrix24\Limits\User::isUserRestricted($USER->GetId())
5203 && !\Bitrix\Bitrix24\Limits\User::isMoreHitsAvailable($USER->GetId())
5204 );
5205 }
5206
5207 public static function IsMysqlDb()
5208 {
5209 global $DB;
5210 return $DB->type == 'MYSQL';
5211 }
5212
5213 public static function IsAdmin()
5214 {
5215 global $USER;
5216 return $USER->IsAdmin() || CModule::IncludeModule('bitrix24') && CBitrix24::IsPortalAdmin($USER->GetId());
5217 }
5218
5219 public static function GetCurrentUserId()
5220 {
5221 global $USER;
5222 return $USER->GetID();
5223 }
5224
5225 public static function loadLoc(): void
5226 {
5227 Loc::loadMessages(__FILE__);
5228 }
5229
5230 protected static function needSendPush(array $arChat): bool
5231 {
5232 if ($arChat['CHAT_TYPE'] === Chat::IM_TYPE_COMMENT)
5233 {
5234 return false;
5235 }
5236
5237 return true;
5238 }
5239
5240 public static function needToSendPublicPull(?string $chatType): bool
5241 {
5242 return $chatType === Chat::IM_TYPE_OPEN_CHANNEL
5243 || $chatType === Chat::IM_TYPE_OPEN_LINE
5244 || $chatType === Chat::IM_TYPE_OPEN
5245 ;
5246 }
5247
5248 protected static function filterRelationsByParentRelations(array $relations, int $chatId): array
5249 {
5250 $userIds = array_keys($relations);
5251
5252 if (empty($userIds))
5253 {
5254 return [];
5255 }
5256
5257 $filteredRelations = [];
5258 $parentRelations = Chat::getInstance($chatId)->getRelationsByUserIds($userIds);
5259 foreach ($parentRelations as $parentRelation)
5260 {
5261 $userId = $parentRelation->getUserId();
5262 if (isset($relations[$userId]))
5263 {
5264 $filteredRelations[$userId] = $relations[$userId];
5265 }
5266 }
5267
5268 return [$filteredRelations, $parentRelations];
5269 }
5270
5271 protected static function getRealPrevId(int $messageId, int $chatId): int
5272 {
5273 $result = \Bitrix\Im\Model\MessageTable::query()
5274 ->setSelect(['ID'])
5275 ->where('CHAT_ID', $chatId)
5276 ->where('ID', '<', $messageId)
5277 ->setOrder(['DATE_CREATE' => 'DESC', 'ID' => 'DESC'])
5278 ->setLimit(1)
5279 ->fetch() ?: []
5280 ;
5281
5282 return (int)($result['ID'] ?? 0);
5283 }
5284
5285 protected static function getChatRelationForMention(Chat $chat, array $users): array
5286 {
5287 $chatRelationsLegacy = [];
5288 foreach ($chat->getRelationsByUserIds($users) as $relation)
5289 {
5290 $chatRelationsLegacy[$relation->getUserId()] = [
5291 'NOTIFY_BLOCK' => $relation->getNotifyBlock() ? 'Y' : 'N',
5292 ];
5293 }
5294
5295 return $chatRelationsLegacy;
5296 }
5297
5298 private static function GetEventByCounterGroup($events, $maxUserInGroup = 100)
5299 {
5300 $groups = Array();
5301 foreach ($events as $userId => $event)
5302 {
5303 $eventCode = $event['groupId'];
5304 if (!isset($groups[$eventCode]))
5305 {
5306 $groups[$eventCode]['event'] = $event;
5307 }
5308 $groups[$eventCode]['users'][] = $userId;
5309 $groups[$eventCode]['count'] = count($groups[$eventCode]['users']);
5310 }
5311
5312 \Bitrix\Main\Type\Collection::sortByColumn($groups, Array('count' => SORT_DESC));
5313
5314 $count = 0;
5315 $finalGroup = Array();
5316 foreach ($groups as $eventCode => $event)
5317 {
5318 if ($count >= $maxUserInGroup)
5319 {
5320 if (isset($finalGroup['other']))
5321 {
5322 $finalGroup['other']['users'] = array_unique(array_merge($finalGroup['other']['users'], $event['users']));
5323 }
5324 else
5325 {
5326 $finalGroup['other'] = $event;
5327 $finalGroup['other']['event']['params']['counter'] = 100;
5328 }
5329 }
5330 else
5331 {
5332 $finalGroup[$eventCode] = $event;
5333 }
5334 $count++;
5335 }
5336
5337 \Bitrix\Main\Type\Collection::sortByColumn($finalGroup, Array('count' => SORT_ASC));
5338
5339 return $finalGroup;
5340 }
5341
5342 protected static function getMessageObject(array $fields): \Bitrix\Im\V2\Message
5343 {
5344 $fields['FROM_USER_ID'] ??= 0;
5345 $fields['AUTHOR_ID'] ??= (int)$fields['FROM_USER_ID'];
5346
5347 if (isset($fields['SYSTEM']))
5348 {
5349 $fields['SYSTEM'] = $fields['SYSTEM'] === 'Y';
5350 }
5351
5352 if (isset($fields['NOTIFY_ANSWER']))
5353 {
5354 $fields['NOTIFY_ANSWER'] = $fields['NOTIFY_ANSWER'] === 'Y';
5355 }
5356
5357 $message = new \Bitrix\Im\V2\Message($fields);
5358
5359 $message->setContextUser((int)$fields['FROM_USER_ID']);
5360
5361 $dialogId = $fields['DIALOG_ID'] ?? $fields['TO_USER_ID'] ?? null;
5362
5363 if ($dialogId)
5364 {
5365 $chatId = \Bitrix\Im\Dialog::getChatId($dialogId, $message->getContext()->getUserId());
5366 if ($chatId)
5367 {
5368 $message->setChatId($chatId);
5369 }
5370 }
5371
5372 if (isset($fields['FILE_MODELS']))
5373 {
5375 }
5376
5377 return $message;
5378 }
5379
5384 protected static function throwLegacyExceptionFromErrors(array $errors): void
5385 {
5386 if (empty($errors))
5387 {
5388 return;
5389 }
5390
5391 if (count($errors) === 1)
5392 {
5393 $error = array_values($errors)[0];
5394 $GLOBALS["APPLICATION"]->ThrowException($error->getMessage(), $error->getCode());
5395
5396 return;
5397 }
5398
5399 $errorMessages = [];
5400 foreach ($errors as $error)
5401 {
5402 $errorMessages[] = ["id" => $error->getCode(), "text" => $error->getMessage()];
5403 }
5404
5405 $exception = new CAdminException($errorMessages);
5406 $GLOBALS["APPLICATION"]->ThrowException($exception);
5407 }
5408}
$arParams
Определения access_dialog.php:21
$count
Определения admin_tab.php:4
$type
Определения options.php:106
$messageFields
Определения callback_ednaru.php:22
if(! $messageFields||!isset($messageFields['message_id'])||!isset($messageFields['status'])||!CModule::IncludeModule("messageservice")) $messageId
Определения callback_ismscenter.php:26
$arResult
Определения generate_coupon.php:16
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static isCallServerEnabled()
Определения call.php:1331
static isConnected($userId)
Определения zoom.php:104
static isActive()
Определения zoom.php:84
static getType($chatData, bool $camelCase=true)
Определения chat.php:45
static filterRelationsByAccess(int $chatId, array $relations)
Определения chat.php:1392
static getRelation($chatId, $params=[])
Определения chat.php:93
static getSafeColors()
Определения color.php:80
static getCode($color)
Определения color.php:103
static isEnabled()
Определения color.php:50
static getSafeColorNames()
Определения color.php:88
static onCommandAdd($messageId, $messageFields)
Определения command.php:295
static objectEncode($params, $pureJson=false)
Определения common.php:28
static isChatId($id)
Определения common.php:58
static getPullExtra()
Определения common.php:127
static getUserId($userId=null)
Определения common.php:73
static getPublicDomain()
Определения common.php:8
static get($userId=null, $options=[])
Определения counter.php:18
static getChatId($dialogId, $userId=null)
Определения dialog.php:93
static hasAccess($dialogId, $userId=null)
Определения dialog.php:184
static getLink($type, $id=null)
Определения common.php:14
static canTransferToLine()
Определения limit.php:36
static canUseVoteHead()
Определения limit.php:20
static canJoinChatUser()
Определения limit.php:28
static canInvite()
Определения user.php:19
static getBirthdayForToday()
Определения user.php:448
Определения Uuid.php:12
static validate(string $uuid)
Определения Uuid.php:87
static indexRecord($id)
Определения message.php:267
static filterExternalUserTypes(array $skipTypes=[])
Определения user.php:31
Определения notify.php:18
static saveNotifyParams(int $messageId, array $values)
Определения notify.php:747
static deleteOldNotifyByTag(int $currentMessageId, array $arParams)
Определения notify.php:644
static raiseChat(\Bitrix\Im\V2\Chat $chat, RelationCollection $relations, ?DateTime $lastActivity=null)
Определения recent.php:1582
static getList($userId=null, $options=[])
Определения recent.php:237
static isBroadcastingEnabled()
Определения settings.php:40
static getLoggerConfig()
Определения settings.php:12
static parse($text, $params=Array())
Определения text.php:28
static filterUserBbCodes(string $text, int $currentUserId)
Определения text.php:554
static getDateConverterParams($text)
Определения text.php:219
static convertHtmlToBbCode($html)
Определения text.php:398
static parseLegacyFormat($text, $params=Array())
Определения text.php:94
static getEmoji($code, $fallbackText='')
Определения text.php:383
static isOnlyEmoji($text)
Определения text.php:233
static decodeEmoji($text)
Определения text.php:378
static getInstance($userId=null)
Определения user.php:45
static getInstance()
Определения ChatFactory.php:37
static sendSharedPull(array $pull)
Определения OpenChannelChat.php:124
static addDiskFilesToPreload(array $diskFiles)
Определения FileCollection.php:227
static initByPreviewUrlId(int $previewUrlId, bool $withHtml=true)
Определения UrlItem.php:60
static getInstanceByMessage(Message $message)
Определения DeleteService.php:73
static disappearMessage(Message $message, int $delay)
Определения DisappearService.php:64
static insert(Message $message)
Определения LastMessages.php:21
const COPILOT_PROMPT_CODE
Определения Params.php:70
static getMessenger()
Определения Locator.php:15
const UPDATED_MESSAGE_ENTITY
Определения Event.php:17
const MESSAGE_ENTITY
Определения Event.php:16
const ADD_EVENT
Определения Event.php:12
const CHAT_ENTITY
Определения Event.php:14
static getInstance()
Определения Logger.php:37
static getInstance()
Определения application.php:98
static getConnection($name="")
Определения application.php:638
static get($moduleId, $name, $default="", $siteId=false)
Определения option.php:30
static getInstance()
Определения servicelocator.php:33
static includeModule($moduleName)
Определения loader.php:67
static getMinTokenSize()
Определения helper.php:76
Определения emoji.php:10
getTimestamp()
Определения date.php:218
static createFromTimestamp($timestamp)
Определения datetime.php:246
Определения uri.php:17
static getInstance()
Определения mobile.php:226
static send()
Определения event.php:387
static add($recipient, array $parameters, $channelType=\CPullChannel::TYPE_PRIVATE)
Определения event.php:22
static getHandlersList($placement, $skipInstallCheck=false, int $userId=null)
Определения placement.php:266
Определения sanitizer.php:23
AddTags($arTags)
Определения sanitizer.php:136
Определения im_chat.php:15
static EnabledExternalLink()
Определения im_disk.php:2468
static GetFiles($chatId, $fileId=false, $checkPermission=true)
Определения im_disk.php:1601
static SaveFromLocalDisk($chatId, $fileId, bool $symlink=false, ?int $userId=null)
Определения im_disk.php:1001
static Enabled()
Определения im_disk.php:1707
static GetLocalDiskFilePath($fileId=0)
Определения im_disk.php:2269
static GetFormatMessage($arParams)
Определения im_message.php:1228
static GetChatId($fromUserId, $toUserId, $createIfNotExists=true)
Определения im_message.php:1459
Определения im_messenger.php:24
static getMessageObject(array $fields)
Определения im_messenger.php:5342
static DisableMessageCheck()
Определения im_messenger.php:5185
static SpeedFileGet($userID, $type=IM_SPEED_MESSAGE)
Определения im_messenger.php:3577
static GetDesktopStatusOnline($userId=null)
Определения im_messenger.php:3276
static UrlAttachDelete($id, $attachId=false, $userId=null)
Определения im_messenger.php:2763
static PreparePushForChat($params)
Определения im_messenger.php:4413
static GetTemplateJS($arParams, $arTemplate)
Определения im_messenger.php:3589
static CheckNetwork()
Определения im_messenger.php:3009
static GetSessionLifeTime()
Определения im_messenger.php:3429
static Update($id, $text, $urlPreview=true, $editFlag=true, $userId=null, $byEvent=false, $convert=false)
Определения im_messenger.php:2020
static PrepareParamsForPush($params)
Определения im_messenger.php:4612
static GetRelationById($ID, bool $raw=false)
Определения im_messenger.php:2963
static SetDesktopLastActivityDate($timestamp, $deviceType=IM_DESKTOP_WINDOWS, $userId=false)
Определения im_messenger.php:3082
static PrepareMessageForPush($message)
Определения im_messenger.php:4659
static CheckNetwork2()
Определения im_messenger.php:3014
GetSonetCode($user_id, $site_id=SITE_ID)
Определения im_messenger.php:5157
static disappearMessage(int $messageId, int $hours, ?int $userId=null)
Определения im_messenger.php:2319
static CheckDesktopStatusOnline($userId=null)
Определения im_messenger.php:3242
static CanUserPerformCalls()
Определения im_messenger.php:3178
static EnableInVersion($version)
Определения im_messenger.php:3038
static SetDesktopStatusOffline($userId=null)
Определения im_messenger.php:3371
static StartWriting($dialogId, $userId=false, $userName="", $byEvent=false, $linesSilentMode=false)
Определения im_messenger.php:4026
static PreparePushForMentionInChat($params)
Определения im_messenger.php:4361
static PrepareMessageForPushIconCallBack($params)
Определения im_messenger.php:5123
static GetById($ID, $params=Array())
Определения im_messenger.php:2918
static GetMessageCounter($userId, $arMessages=Array())
Определения im_messenger.php:3490
static GetCachePath($id)
Определения im_messenger.php:5152
static IsEnabledMessageCheck()
Определения im_messenger.php:5191
static GetCurrentUserId()
Определения im_messenger.php:5219
static Add($arFields)
Определения im_messenger.php:128
static SetDesktopVersion($version)
Определения im_messenger.php:3057
static PrepareMessageForPushSendPutCallBack($params)
Определения im_messenger.php:5117
static IsMobileRequest()
Определения im_messenger.php:1914
static ExecCommand($id, $botId, $command, $commandParams='', $userId=null, $byEvent=false)
Определения im_messenger.php:2674
static GetDesktopVersion()
Определения im_messenger.php:3075
static Like($id, $action='auto', $userId=null, $byEvent=false, $withReaction=true)
Определения im_messenger.php:2447
static CheckEnableOpenChat()
Определения im_messenger.php:3004
static GetCallCardRestApps()
Определения im_messenger.php:3196
static throwLegacyExceptionFromErrors(array $errors)
Определения im_messenger.php:5384
static CheckInstallDesktop()
Определения im_messenger.php:3023
static SetDesktopStatusOnline($userId=null, $cache=true)
Определения im_messenger.php:3299
static GetSettings($userId=false)
Определения im_messenger.php:3403
static loadLoc()
Определения im_messenger.php:5225
static IsAdmin()
Определения im_messenger.php:5213
static CanCallByLimits()
Определения im_messenger.php:3155
static EnableMessageCheck()
Определения im_messenger.php:5180
static SpeedFileExists($userID, $type=IM_SPEED_MESSAGE)
Определения im_messenger.php:3562
static CheckPhoneStatus()
Определения im_messenger.php:3121
static CanUserCallUserNumber()
Определения im_messenger.php:3142
static GetUnreadCounter($userId)
Определения im_messenger.php:3452
static Share($id, $type, $date='')
Определения im_messenger.php:2283
static LinesSessionVote($dialogId, $messageId, $action, $userId=null)
Определения im_messenger.php:2368
static PrepareSmiles()
Определения im_messenger.php:4066
static CanUserCallAnyNumber()
Определения im_messenger.php:3165
static CanInterceptCall()
Определения im_messenger.php:3187
static needToSendPublicPull(?string $chatType)
Определения im_messenger.php:5240
const MESSAGE_LIMIT
Определения im_messenger.php:28
static PreparePushForPrivate($params)
Определения im_messenger.php:4510
static IsMysqlDb()
Определения im_messenger.php:5207
static SpeedFileDelete($userID, $type=IM_SPEED_MESSAGE)
Определения im_messenger.php:3551
__construct($user_id=false)
Определения im_messenger.php:30
static GetMobileDialogTemplateJS($arParams, $arTemplate)
Определения im_messenger.php:3887
static needSendPush(array $arChat)
Определения im_messenger.php:5230
static decodeEmoji($value)
Определения im_messenger.php:4343
static SpeedFileCreate($userID, $value, $type=IM_SPEED_MESSAGE)
Определения im_messenger.php:3538
static IsDesktopEnvironment()
Определения im_messenger.php:3046
static getRealPrevId(int $messageId, int $chatId)
Определения im_messenger.php:5271
static filterRelationsByParentRelations(array $relations, int $chatId)
Определения im_messenger.php:5248
static PrepareParamsForPull($params)
Определения im_messenger.php:4290
static getChatRelationForMention(Chat $chat, array $users)
Определения im_messenger.php:5285
static GetV2TemplateJS($arResult)
Определения im_messenger.php:3844
static CheckPossibilityUpdateMessage($type, $id, $userId=null)
Определения im_messenger.php:1919
static SendMention($params)
Определения im_messenger.php:4103
static GetFormatFilesMessageOut($files)
Определения im_messenger.php:3409
static getPhoneSettings()
Определения im_messenger.php:3857
static PrepareEventForPush($command, $event)
Определения im_messenger.php:4739
static GetTelephonyAvailableLines($userId=null)
Определения im_messenger.php:3220
static CanUserCallCrmNumber()
Определения im_messenger.php:3129
static Delete($id, $userId=null, $completeDelete=false, $byEvent=false)
Определения im_messenger.php:2336
static IsBitrix24UserRestricted()
Определения im_messenger.php:5196
static CheckXmppStatusOnline()
Определения im_messenger.php:2993
static GetDefaultTelephonyLine($userId=null)
Определения im_messenger.php:3231
static GetNotifyAccess($userId, $moduleId, $eventId, $clientId)
Определения im_settings.php:255
const CLIENT_SITE
Определения im_settings.php:15
const CLIENT_PUSH
Определения im_settings.php:18
static Get($userId=false)
Определения im_settings.php:34
Определения im_share.php:8
Определения user.php:6037
global $CACHE_MANAGER
Определения clear_component_cache.php:7
$templateId
Определения component_props2.php:51
$arTemplate
Определения component_props.php:26
$hours
Определения cron_html_pages.php:15
$arFields
Определения dblapprove.php:5
$userList
Определения discount_coupon_list.php:276
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$_REQUEST["admin_mnu_menu_id"]
Определения get_menu.php:8
$result
Определения get_property_values.php:14
if($ajaxMode) $ID
Определения get_user.php:27
$errors
Определения iblock_catalog_edit.php:74
$filter
Определения iblock_catalog_list.php:54
const IM_DESKTOP_MAC
Определения include.php:73
const IM_DESKTOP_LINUX
Определения include.php:74
const IM_CHECK_UPDATE
Определения include.php:69
const IM_MESSAGE_CHAT
Определения include.php:23
const IM_MESSAGE_OPEN
Определения include.php:24
const IM_MESSAGE_SYSTEM
Определения include.php:21
const IM_SPEED_MESSAGE
Определения include.php:66
const IM_SPEED_GROUP
Определения include.php:67
const IM_NOTIFY_SYSTEM
Определения include.php:38
const IM_NOTIFY_CONFIRM
Определения include.php:36
const IM_NOTIFY_FROM
Определения include.php:37
const IM_MESSAGE_PRIVATE
Определения include.php:22
const IM_MESSAGE_OPEN_LINE
Определения include.php:26
const IM_CHECK_DELETE
Определения include.php:70
const IM_SPEED_NOTIFY
Определения include.php:65
const IM_DESKTOP_WINDOWS
Определения include.php:72
global $DB
Определения cron_frame.php:29
global $USER
Определения csv_new_run.php:40
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
$application
Определения bitrix.php:23
const SITE_DIR(!defined('LANG'))
Определения include.php:72
$arPolicy
Определения include.php:194
$groups
Определения options.php:30
$mid
Определения options.php:27
$status
Определения session.php:10
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
htmlspecialcharsback($str)
Определения tools.php:2693
IsModuleInstalled($module_id)
Определения tools.php:5301
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
Определения tools.php:2701
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
GetMessage($name, $aReplace=null)
Определения tools.php:3397
$map
Определения config.php:5
Определения contextmenu.php:9
Определения auth.php:9
Определения Uuid.php:3
$value
Определения Param.php:39
Определения ChatsSync.php:3
Определения ActionUuid.php:3
Определения culture.php:9
Определения arrayresult.php:2
Определения ufield.php:9
Определения base32.php:2
Определения collection.php:2
$user
Определения mysql_to_pgsql.php:33
$files
Определения mysql_to_pgsql.php:30
$GLOBALS['____1690880296']
Определения license.php:1
$entityId
Определения payment.php:4
$time
Определения payment.php:61
$message
Определения payment.php:8
$arFiles
Определения options.php:60
$counter
Определения options.php:5
$event
Определения prolog_after.php:141
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$config
Определения quickway.php:69
$fileName
Определения quickway.php:305
if(empty($signedUserToken)) $key
Определения quickway.php:257
$text
Определения template_pdf.php:79
else $userName
Определения order_form.php:75
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$title
Определения pdf.php:123
$matches
Определения index.php:22
$counters
Определения options.php:100
$arRes
Определения options.php:104
$site_id
Определения sonet_set_content_view.php:9
const SITE_ID
Определения sonet_set_content_view.php:12
$error
Определения subscription_card_product.php:20
$action
Определения file_dialog.php:21
$GLOBALS['_____370096793']
Определения update_client.php:1
$url
Определения iframe.php:7
$dbRes
Определения yandex_detail.php:168
$fields
Определения yandex_run.php:501