27 'SUCCESS_RESULT' => [],
31 $messages = $this->fillFiles($messages);
34 foreach ($messages as $index => $message)
36 $externalId = $message[
'externalId'] ===
'' ? $index : $message[
'externalId'];
37 $addResult = $this->addMessage($message);
38 if (!$addResult->isSuccess())
40 $sendStubResult = $this->sendStubMessage($message);
41 if (!$sendStubResult->isSuccess())
43 return $sendStubResult;
45 $error = $addResult->getErrors()[0];
46 $resultArray[
'ERROR_RESULT'][] = [
47 'ID' => $sendStubResult->getResult(),
48 'EXTERNAL_ID' => $externalId,
49 'ERROR_CODE' => $error->getCode(),
50 'ERROR_MESSAGE' => $error->getMessage(),
55 $resultArray[
'SUCCESS_RESULT'][] = [
56 'ID' => $addResult->getResult()[
'ID'],
57 'EXTERNAL_ID' => $externalId,
59 $this->lastDateCreate = $this->getDateTimeFromAtom($message[
'dateCreate']);
60 if (isset($message[
'fileId']))
62 $addedFiles[] = (int)$message[
'fileId'];
66 $this->increaseFilesVersion($addedFiles);
68 return (
new Result())->setResult($resultArray);
75 'SUCCESS_RESULT' => [],
79 $ids = array_column($messages,
'id');
80 $chatIds = $this->getChatIdsByMessageIds($ids);
81 $messages = $this->fillFiles($messages);
84 foreach ($messages as $message)
86 $message[
'chatId'] = $chatIds[(int)$message[
'id']] ??
null;
87 $updateResult = $this->updateMessage($message);
88 if (!$updateResult->isSuccess())
90 $error = $updateResult->getErrors()[0];
91 $resultArray[
'ERROR_RESULT'][] = [
92 'ID' =>(int)$message[
'id'],
93 'ERROR_CODE' => $error->getCode(),
94 'ERROR_MESSAGE' => $error->getMessage(),
99 $resultArray[
'SUCCESS_RESULT'][] = $updateResult->getResult();
100 if (isset($message[
'fileId']))
102 $addedFiles[] = (int)$message[
'fileId'];
106 $this->increaseFilesVersion($addedFiles);
108 return $result->setResult($resultArray);
111 private function fillFiles(array $messages): array
113 $files = $this->getFiles($messages);
115 foreach ($messages as $index => $message)
117 if (isset($message[
'fileId']))
119 $messages[$index][
'file'] = $files[(int)$message[
'fileId']] ??
null;
126 private function getFiles(array $messages): array
130 foreach ($messages as $message)
132 if (isset($message[
'fileId']) && (
int)$message[
'fileId'] > 0)
134 $fileIds[] = (int)$message[
'fileId'];
143 $files = File::getModelList([
'filter' => [
'ID' => $fileIds]]);
146 foreach ($files as $file)
148 $filesById[$file->getId()] = $file;
154 private function increaseFilesVersion(array $files): void
161 $implodeFileId = implode(
',', $files);
162 $sql =
"UPDATE b_disk_object SET GLOBAL_CONTENT_VERSION=2 WHERE ID IN ({$implodeFileId})";
166 private function addMessage(array $message): Result
168 $result =
new Result();
170 $validateResult = $this->validateFields($message);
171 if (!$validateResult->isSuccess())
173 return $validateResult;
175 $message = $validateResult->getResult();
176 $messageFieldsResult = $this->getMessageFields($message);
177 $messageId = \CIMMessenger::Add($messageFieldsResult);
179 if ($messageId ===
false)
181 return $result->addError($this->getErrorLegacy());
184 return $result->setResult([
'ID' => $messageId]);
187 private function checkFileAccess(array $message): Result
189 $result =
new Result();
191 if (!isset($message[
'file']))
195 if ((
int)$message[
'file']->getParentId() !== (
int)$this->chat[
'DISK_FOLDER_ID'])
203 private function updateMessage(array $message): Result
205 $result =
new Result();
206 $id = (int)$message[
'id'];
207 if ((
int)$this->chat[
'ID'] !== $message[
'chatId'])
209 return $result->addError(
new MessageError(MessageError::MESSAGE_NOT_FOUND));
212 $validateResult = $this->validateParams($message);
214 if (!$validateResult->isSuccess())
216 return $validateResult;
219 $params = $validateResult->getResult();
223 \CIMMessageParam::Set($id, $params);
226 if (isset($message[
'message']))
228 $urlPreview = !(isset($message[
'urlPreview']) && $message[
'urlPreview'] ===
"N");
229 $isSuccessUpdate = \CIMMessenger::Update($id, $message[
'message'], $urlPreview,
false,
null,
false,
true);
230 if (!$isSuccessUpdate)
236 return $result->setResult([
'ID' => $id]);
239 private function getErrorLegacy():
Error
242 $error = $APPLICATION->GetException();
243 if ($error instanceof \CAdminException)
246 $errorMessage = $error->messages[0][
'text'] ??
'';
250 $errorCode = $error->GetID();
251 $errorMessage = $error->GetString();
254 return new Error($errorCode, $errorMessage);
257 private function getChatIdsByMessageIds(array $messageIds): array
260 if (empty($messageIds))
265 $messages = MessageTable::query()
266 ->setSelect([
'ID',
'CHAT_ID'])
267 ->whereIn(
'ID', $messageIds)
271 foreach ($messages as $message)
273 $result[$message->getId()] = $message->getChatId();
279 private function sendStubMessage(array $originalMessage): Result
281 $result =
new Result();
282 $chatId = (int)$this->chat[
'ID'];
283 $originalDate = $this->getDateTimeFromAtom($originalMessage[
'dateCreate']);
284 if (isset($originalDate) && !$this->hasDateError())
286 $date = $originalDate;
290 $date = $this->getLastDateCreate();
298 $messageId = \CIMMessenger::Add([
300 'MESSAGE_DATE' => $date->toString(),
301 'FROM_USER_ID' => $originalMessage[
'authorId'] ?? 0,
302 'TO_CHAT_ID' => $chatId,
303 'MESSAGE_TYPE' => $this->chat[
'MESSAGE_TYPE'],
304 'SYSTEM' => $originalMessage[
'system'],
305 'URL_PREVIEW' =>
'N',
308 'SKIP_COMMAND' =>
'Y',
309 'SKIP_USER_CHECK' =>
'Y',
313 return $result->setResult($messageId);
316 private function getLastDateCreate(): ?DateTime
318 if (isset($this->lastDateCreate))
320 return $this->lastDateCreate;
323 $result = MessageTable::query()
324 ->setSelect([
'DATE_CREATE'])
325 ->where(
'CHAT_ID', (
int)$this->chat[
'ID'])
326 ->setOrder([
'DATE_CREATE' =>
'DESC'])
331 $this->lastDateCreate = $result ? $result[
'DATE_CREATE'] :
null;
333 return $this->lastDateCreate;
336 private function hasDateError(): bool
339 $error = $APPLICATION->GetException();
340 if ($error ===
false)
344 if ($error instanceof \CAdminException)
346 foreach ($error->messages as $message)
348 if ($message[
'id'] ??
'' ===
'MESSAGE_DATE')
356 return $error->GetID() ===
'MESSAGE_DATE';
362 private function validateFields(array $message): Result
364 $result =
new Result();
365 $dateCreate = $this->getDateTimeFromAtom($message[
'dateCreate']);
366 if (!isset($dateCreate))
370 if ($this->getLastDateCreate() !==
null && $dateCreate->getTimestamp() < $this->getLastDateCreate()->getTimestamp())
374 $validateParams = $this->validateParams($message);
375 if (!$validateParams->isSuccess())
377 return $validateParams;
379 $params = $validateParams->getResult();
381 $message[
'dateCreate'] = $dateCreate->toString();
382 $message[
'keyboard'] = $params[
'KEYBOARD'] ??
null;
383 $message[
'menu'] = $params[
'MENU'] ??
null;
384 $message[
'attach'] = $params[
'ATTACH'] ??
null;
385 $message[
'fileId'] = $params[
'FILE_ID'] ??
null;
387 return $result->setResult($message);
390 private function validateParams(array $message): Result
395 'FILE_ID' => $this->getFileIdParams($message),
396 'KEYBOARD' => $this->getKeyboard($message),
397 'MENU' => $this->getMenu($message),
398 'ATTACH' => $this->getAttach($message)
401 foreach ($results as $paramName => $result)
403 if (!$result->isSuccess())
407 if ($result->getResult() !==
null)
409 $params[$paramName] = $result->getResult();
413 return (
new Result())->setResult($params);
416 private function getMessageFields(array $message): array
419 'MESSAGE' => $message[
'message'],
420 'MESSAGE_DATE' => $message[
'dateCreate'],
421 'FROM_USER_ID' => (int)$message[
'authorId'],
422 'TO_CHAT_ID' => (
int)$this->chat[
'ID'],
423 'MESSAGE_TYPE' => $this->chat[
'MESSAGE_TYPE'],
424 'SYSTEM' => $message[
'system'],
425 'ATTACH' => $message[
'attach'],
426 'KEYBOARD' => $message[
'keyboard'],
427 'MENU' => $message[
'menu'],
428 'URL_PREVIEW' =>
'N',
429 'FILES' => $message[
'fileId'],
432 'SKIP_COMMAND' =>
'Y',
433 'SKIP_USER_CHECK' =>
'Y',
438 private function getDateTimeFromAtom(
string $dateAtom): ?DateTime
443 private function getFileIdParams(array $message): Result
445 $result =
new Result();
447 if (isset($message[
'fileId']))
450 if ($message[
'fileId'] ===
'N')
452 return $result->setResult([]);
454 $fileCheckResult = $this->checkFileAccess($message);
455 if (!$fileCheckResult->isSuccess())
457 return $fileCheckResult;
459 $fileId = [(int)$message[
'fileId']];
462 return $result->setResult($fileId);
465 private function getKeyboard(array $message): Result
467 $result =
new Result();
469 if (isset($message[
'keyboard']))
471 if ($message[
'keyboard'] ===
'N')
473 return $result->setResult(
'N');
476 if (!isset($message[
'keyboard'][
'BUTTONS']))
478 $keyboard[
'BUTTONS'] = $message[
'keyboard'];
482 $keyboard = $message[
'keyboard'];
484 $keyboard[
'BOT_ID'] = $message[
'botId'];
485 $keyboard = \Bitrix\Im\Bot\Keyboard::getKeyboardByJson($keyboard);
486 if (!isset($keyboard))
488 return $result->addError(
new ImportError(
'KEYBOARD_ERROR',
'Incorrect keyboard params'));
490 if (!$keyboard->isAllowSize())
492 return $result->addError(
new ImportError(
'KEYBOARD_OVERSIZE',
'You have exceeded the maximum allowable size of keyboard'));
496 return $result->setResult($keyboard);
499 private function getMenu(array $message): Result
501 $result =
new Result();
503 if (isset($message[
'menu']))
505 if ($message[
'menu'] ===
'N')
507 return $result->setResult(
'N');
510 if (!isset($message[
'menu'][
'ITEMS']))
512 $menu[
'ITEMS'] = $message[
'menu'];
516 $menu = $message[
'menu'];
518 $menu[
'BOT_ID'] = $message[
'botId'];
519 $menu = \Bitrix\Im\Bot\ContextMenu::getByJson($menu);
522 return $result->addError(
new ImportError(
'MENU_ERROR',
'Incorrect menu params'));
524 if (!$menu->isAllowSize())
526 return $result->addError(
new ImportError(
'MENU_OVERSIZE',
'You have exceeded the maximum allowable size of menu'));
530 return $result->setResult($menu);
533 private function getAttach(array $message): Result
535 $result =
new Result();
537 if (isset($message[
'attach']))
539 if ($message[
'attach'] ===
'N')
541 return $result->setResult(
'N');
543 $attach = \CIMMessageParamAttach::GetAttachByJson($message[
'attach']);
546 return $result->addError(
new ImportError(
'ATTACH_ERROR',
'Incorrect attach params'));
548 if (!$attach->IsAllowSize())
550 return $result->addError(
new ImportError(
'ATTACH_OVERSIZE',
'You have exceeded the maximum allowable size of attach'));
554 return $result->setResult($attach);