1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
MentionService.php
См. документацию.
1<?php
2
3namespace Bitrix\Im\V2\Message\Send;
4
5use Bitrix\Im\Text;
6use Bitrix\Im\V2\Anchor\AnchorFeature;
7use Bitrix\Im\V2\Anchor\DI\AnchorContainer;
8use Bitrix\Main\Localization\Loc;
9use Bitrix\Im\V2\Message;
10use Bitrix\Im\V2\Chat;
11use Bitrix\Im\V2\Common\ContextCustomer;
12use Bitrix\Pull\Push;
13use CIMNotify;
14
16{
17 use ContextCustomer;
18
19 private SendingConfig $sendingConfig;
20
24 public function __construct(?SendingConfig $sendingConfig = null)
25 {
26 if ($sendingConfig === null)
27 {
28 $sendingConfig = new SendingConfig();
29 }
30 $this->sendingConfig = $sendingConfig;
31 }
32
33 public function isPullEnable(): bool
34 {
35 static $enable;
36 if ($enable === null)
37 {
38 $enable = \Bitrix\Main\Loader::includeModule('pull');
39 }
40 return $enable;
41 }
42
43 public function processMentions(Message $message): void
44 {
45 $userName = $message->getAuthor()?->getName();
46 if (!$userName)
47 {
48 return;
49 }
50
51 $this->processMessageAnchors($message);
52
53 $chat = $this->getChat($message);
54 if ($this->canMention($message, $chat))
55 {
56 $this->sendMentions($message);
57 }
58 }
59
60 public function updateMentions(Message $previousMessage, Message $newMessage): void
61 {
62 if ($previousMessage->getMessage() === $newMessage->getMessage())
63 {
64 return;
65 }
66
67 $this->updateMessageAnchors($previousMessage, $newMessage);
68
69 $chat = $this->getChat($newMessage);
70 if ($this->canMention($newMessage, $chat))
71 {
72 $this->updateUsersMentions($previousMessage, $newMessage);
73 }
74 }
75
76 public function sendMentions(Message $message): void
77 {
78 $chat = $this->getChat($message);
79
80 $mentionedUserIds = $message->getUserIdsToSendMentions();
81 unset($mentionedUserIds[$message->getAuthorId()]);
82
83 $this->sendMentionsToUsers($message, $chat, $mentionedUserIds);
84 }
85
86 protected function needToSendPull(): bool
87 {
88 return true;
89 }
90
91 protected function getChat(Message $message): Chat
92 {
93 return $message->getChat();
94 }
95
96 private function preparePushForMentionInChat(Message $message): array
97 {
98 $chat = $this->getChat($message);
99 $avatarUser = $message->getAuthor()?->getAvatar();
100 $avatarChat = $chat->getAvatar(false, true);
101 $pushText = $this->preparePushMessage($message);
102 $chatTitle = htmlspecialcharsbx(Text::decodeEmoji($chat->getTitle() ?? ''));
103
104 $result = [];
105 $result['push'] = [];
106
107 $result['module_id'] = 'im';
108 $result['push']['params'] = [
109 'TAG' => 'IM_CHAT_' . $chat->getId(),
110 'CHAT_TYPE' => $chat->getType(),
111 'CATEGORY' => 'ANSWER',
112 'URL' => SITE_DIR . 'mobile/ajax.php?mobile_action=im_answer',
113 'PARAMS' => [
114 'RECIPIENT_ID' => 'chat' . $chat->getId(),
115 ],
116 ];
117 $result['push']['type'] = ($chat->getType() === Chat::IM_TYPE_OPEN ? 'openChat' : 'chat');
118 $result['push']['tag'] = 'IM_CHAT_' . $chat->getId();
119 $result['push']['sub_tag'] = 'IM_MESS';
120 $result['push']['app_id'] = 'Bitrix24';
121 $result['push']['message'] = $pushText;
122 $result['push']['advanced_params'] = [
123 'group' => ($chat->getEntityType() === Chat::ENTITY_TYPE_LINE ? 'im_lines_message' : 'im_message'),
124 'avatarUrl' => $avatarChat ?: $avatarUser,
125 'senderName' => $chatTitle,
126 'senderMessage' => $pushText,
127 ];
128
129 return $result;
130 }
131
132 private function preparePushMessage(Message $message): string
133 {
134 Message::loadPhrases();
135 \CIMMessenger::loadLoc();
136 $chat = $this->getChat($message);
137 $chatTitle = mb_substr(Text::decodeEmoji($chat->getTitle() ?? ''), 0, 32);
138 $author = $message->getAuthor();
139 $userName = $author?->getName() ?? '';
140 $userGender = $author?->getGender() ?? 'M';
141
142 $pushMessage = $message->getMessage();
143
144 $pushFiles = '';
145 if ($message->hasFiles())
146 {
147 foreach ($message->getFiles() as $file)
148 {
149 $pushFiles .= " [".Loc::getMessage('IM_MESSAGE_FILE').": ".$file->getDiskFile()->getName()."]";
150 }
151 $pushMessage .= $pushFiles;
152 }
153
154 $hasAttach = mb_strpos($pushMessage, '[ATTACH=') !== false;
155
156 $pushMessage = preg_replace("/\[CODE\](.*?)\[\/CODE\]/si", " [".Loc::getMessage('IM_MESSAGE_CODE')."] ", $pushMessage);
157 $pushMessage = preg_replace("/\[s\].*?\[\/s\]/i", "-", $pushMessage);
158 $pushMessage = preg_replace("/\[[bui]\](.*?)\[\/[bui]\]/i", "$1", $pushMessage);
159 $pushMessage = preg_replace("/\\[url\\](.*?)\\[\\/url\\]/iu", "$1", $pushMessage);
160 $pushMessage = preg_replace("/\\[url\\s*=\\s*((?:[^\\[\\]]++|\\[ (?: (?>[^\\[\\]]+) | (?:\\1) )* \\])+)\\s*\\](.*?)\\[\\/url\\]/ixsu", "$2", $pushMessage);
161 $pushMessage = preg_replace_callback("/\[USER=([0-9]{1,})\]\[\/USER\]/i", ['\Bitrix\Im\Text', 'modifyShortUserTag'], $pushMessage);
162 $pushMessage = preg_replace("/\[USER=([0-9]+)( REPLACE)?](.+?)\[\/USER]/i", "$3", $pushMessage);
163 $pushMessage = preg_replace("/\[CHAT=([0-9]{1,})\](.*?)\[\/CHAT\]/i", "$2", $pushMessage);
164 $pushMessage = preg_replace_callback("/\[SEND(?:=(?:.+?))?\](?:.+?)?\[\/SEND]/i", ['\Bitrix\Im\Text', 'modifySendPut'], $pushMessage);
165 $pushMessage = preg_replace_callback("/\[PUT(?:=(?:.+?))?\](?:.+?)?\[\/PUT]/i", ['\Bitrix\Im\Text', 'modifySendPut'], $pushMessage);
166 $pushMessage = preg_replace("/\[CALL(?:=(.+?))?\](.+?)?\[\/CALL\]/i", "$2", $pushMessage);
167 $pushMessage = preg_replace("/\[PCH=([0-9]{1,})\](.*?)\[\/PCH\]/i", "$2", $pushMessage);
168 $pushMessage = preg_replace_callback("/\[ICON\=([^\]]*)\]/i", ['\Bitrix\Im\Text', 'modifyIcon'], $pushMessage);
169 $pushMessage = preg_replace_callback('/\[TIMESTAMP=(\d+) FORMAT=([^\]]*)\]/i', [Text::class, 'modifyTimestampCode'], $pushMessage);
170 $pushMessage = preg_replace('#\-{54}.+?\-{54}#s', " [".Loc::getMessage('IM_MESSAGE_QUOTE')."] ", str_replace('#BR#', ' ', $pushMessage));
171 $pushMessage = preg_replace('/^(>>(.*)(\n)?)/mi', " [".Loc::getMessage('IM_MESSAGE_QUOTE')."] ", str_replace('#BR#', ' ', $pushMessage));
172
173 if (!$pushFiles && !$hasAttach && $message->getParams()->isSet('ATTACH'))
174 {
175 $pushMessage .= " [".Loc::getMessage('IM_MESSAGE_ATTACH')."]";
176 }
177
178 return
179 Loc::getMessage('IM_MESSAGE_MENTION_PUSH_2_'.$userGender, ['#USER#' => $userName, '#TITLE#' => $chatTitle])
180 . ': '
181 . $pushMessage;
182 }
183
184 private function prepareNotifyMail(string $chatTitle, string $userGender): callable
185 {
186 return fn (?string $languageId = null) => Loc::getMessage(
187 $this->getNotifyTextCode($userGender),
188 ['#TITLE#' => $chatTitle],
189 $languageId
190 );
191 }
192
193 private function prepareNotifyMessage(string $chatTitle, Message $message, string $userGender): callable
194 {
195 return fn (?string $languageId = null) => Loc::getMessage(
196 $this->getNotifyTextCode($userGender),
197 ['#TITLE#' => $this->getTitleWithContext($chatTitle, $message)],
198 $languageId
199 );
200 }
201
202 protected function getTitleWithContext(string $title, Message $message): string
203 {
204 $chat = $this->getChat($message);
205
206 return "[CHAT={$chat->getId()}]{$title}[/CHAT]";
207 }
208
209 protected function getNotifyTextCode(string $userGender): string
210 {
211 return "IM_MESSAGE_MENTION_{$userGender}";
212 }
213
214 private function canMention(Message $message, Chat $chat): bool
215 {
216 if (
217 !$chat->allowMention()
218 || !$chat->getChatId()
219 || !$message->getMessage()
220 || !$message->getAuthorId()
221 || $message->isSystem()
222 )
223 {
224 return false;
225 }
226
227 return true;
228 }
229
230 private function sendMentionsToUsers(Message $message, Chat $chat, array $mentionedUserIds): void
231 {
232 $userGender = $message->getAuthor()?->getGender() === 'F' ? 'F' : 'M';
233 $chatTitle = mb_substr(Text::decodeEmoji($chat->getTitle()), 0, 32);
234
235 foreach ($mentionedUserIds as $userId)
236 {
237 if($this->shouldSendMentionNotification($chat, $userId))
238 {
240 "TO_USER_ID" => $userId,
241 "FROM_USER_ID" => $message->getAuthorId(),
242 "NOTIFY_TYPE" => \IM_NOTIFY_FROM,
243 "NOTIFY_MODULE" => "im",
244 "NOTIFY_EVENT" => "mention",
245 "NOTIFY_TAG" => 'IM|MENTION|' . $chat->getChatId(),
246 "NOTIFY_SUB_TAG" => 'IM_MESS_' . $chat->getChatId() . '_' . $userId,
247 "NOTIFY_MESSAGE" => $this->prepareNotifyMessage($chatTitle, $message, $userGender),
248 "NOTIFY_MESSAGE_OUT" => $this->prepareNotifyMail($chatTitle, $userGender),
249 ];
250 CIMNotify::Add($messageFields);
251 }
252
253 if ($this->isPullEnable() && $this->needToSendPull())
254 {
255 Push::add($userId, $this->preparePushForMentionInChat($message));
256 }
257 }
258 }
259
260 protected function shouldSendMentionNotification(Chat $chat, int $userId): bool
261 {
262 $relation = $chat->getRelationByUserId($userId);
263
264 return ($chat instanceof Chat\OpenChannelChat || $chat instanceof Chat\OpenChat) && !$relation;
265 }
266
267 private function deleteMentionNotifications(Message $message, array $unmentionedUserIds): void
268 {
269 foreach ($unmentionedUserIds as $userId)
270 {
271 CIMNotify::DeleteBySubTag('IM_MESS_' . $message->getChatId() . '_' . $userId);
272 }
273 }
274
275 private function processMessageAnchors(Message $message): void
276 {
277 $anchorMentionedUserIds = $message->getUserIdsToSendMentionAnchors();
278 unset($anchorMentionedUserIds[$message->getAuthorId()]);
279
280 $this->addAnchors($message, $anchorMentionedUserIds);
281 }
282
283 private function updateMessageAnchors(Message $previousMessage, Message $newMessage): void
284 {
285 $previousMentionedUserIds = $previousMessage->getUserIdsToSendMentionAnchors();
286 $newMentionedUserIds = $newMessage->getUserIdsToSendMentionAnchors();
287
288 unset(
289 $previousMentionedUserIds[$previousMessage->getAuthorId()],
290 $newMentionedUserIds[$newMessage->getAuthorId()]
291 );
292
293 $toDelete = array_diff_key($previousMentionedUserIds, $newMentionedUserIds);
294 $this->deleteAnchors($newMessage, $toDelete);
295
296 $toAdd = array_diff_key($newMentionedUserIds, $previousMentionedUserIds);
297 $this->addAnchors($newMessage, $toAdd);
298 }
299
300 private function updateUsersMentions(Message $previousMessage, Message $newMessage): void
301 {
302 $chat = $this->getChat($newMessage);
303
304 $previousMentionedUserIds = $previousMessage->getUserIdsToSendMentions();
305 $newMentionedUserIds = $newMessage->getUserIdsToSendMentions();
306
307 unset(
308 $previousMentionedUserIds[$previousMessage->getAuthorId()],
309 $newMentionedUserIds[$newMessage->getAuthorId()]
310 );
311
312 $toDelete = array_diff_key($previousMentionedUserIds, $newMentionedUserIds);
313 $this->deleteMentionNotifications($newMessage, $toDelete);
314
315 $toAdd = array_diff_key($newMentionedUserIds, $previousMentionedUserIds);
316 $this->sendMentionsToUsers($newMessage, $chat, $toAdd);
317 }
318
319 private function addAnchors(Message $message, array $mentionedUserIds): void
320 {
321 if (!AnchorFeature::isOn())
322 {
323 return;
324 }
325
326 $anchorService = AnchorContainer::getInstance()
327 ->getAnchorService($message)
328 ->setContext($this->getContext());
329
330 $anchorService->addMentionAnchor($mentionedUserIds);
331 }
332
333 private function deleteAnchors(Message $message, array $unmentionedUserIds): void
334 {
335 $anchorService = AnchorContainer::getInstance()
336 ->getAnchorService($message)
337 ->setContext($this->getContext());
338
339 $anchorService->deleteUsersMentionAnchors($unmentionedUserIds);
340 }
341}
$messageFields
Определения callback_ednaru.php:22
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static decodeEmoji($text)
Определения text.php:378
getChat(Message $message)
Определения MentionService.php:91
processMentions(Message $message)
Определения MentionService.php:43
getNotifyTextCode(string $userGender)
Определения MentionService.php:209
sendMentions(Message $message)
Определения MentionService.php:76
__construct(?SendingConfig $sendingConfig=null)
Определения MentionService.php:24
updateMentions(Message $previousMessage, Message $newMessage)
Определения MentionService.php:60
getTitleWithContext(string $title, Message $message)
Определения MentionService.php:202
shouldSendMentionNotification(Chat $chat, int $userId)
Определения MentionService.php:260
getMessage()
Определения Message.php:906
add($name, $value)
Определения configuration.php:141
static includeModule($moduleName)
Определения loader.php:67
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
const IM_NOTIFY_FROM
Определения include.php:37
const SITE_DIR(!defined('LANG'))
Определения include.php:72
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
Определения tools.php:2701
Определения Uuid.php:3
$message
Определения payment.php:8
else $userName
Определения order_form.php:75
$title
Определения pdf.php:123