1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
call.php
См. документацию.
1<?php
2
4
5use Bitrix\Call\NotifyService;
19use Bitrix\Call\Settings;
20use Bitrix\Call\Integration\AI\CallAISettings;
21
22
24{
25 protected const LOCK_TTL = 10; // in seconds
26
37 public function createAction(int $type, string $provider, string $entityType, string $entityId, bool $joinExisting = false): ?array
38 {
39 Loader::includeModule('call');
40
41 $currentUserId = $this->getCurrentUser()->getId();
42
43 $call = null;
44
45 $lockName = static::getLockNameWithEntityId($entityType, $entityId, $currentUserId);
46 if (!Application::getConnection()->lock($lockName, 3))
47 {
48 if ($joinExisting)
49 {
50 $call = CallFactory::searchActive($type, $provider, $entityType, $entityId);
51 }
52
53 if (!$call)
54 {
55 $this->addError(new Error("Could not get exclusive lock", "could_not_lock"));
56 return null;
57 }
58 }
59
60 if (!$call && $joinExisting)
61 {
62 $call = CallFactory::searchActive($type, $provider, $entityType, $entityId);
63 }
64
65 if (!$call && ($provider == \Bitrix\Im\Call\Call::PROVIDER_PLAIN))
66 {
67 if (CallFactory::hasUserActiveCalls((int)$entityId))
68 {
69 $chat = ChatFactory::getInstance()->getPrivateChat($currentUserId, (int)$entityId);
70 if ($chat->getId() > 0)
71 {
72 $notifyService = NotifyService::getInstance();
73 $notifyService->sendOpponentBusyMessage($currentUserId, (int)$entityId);
74 }
75
76 $this->addError(new Error('User is currently busy on another call', 'user_is_busy'));
77 Application::getConnection()->unlock($lockName);
78 return null;
79 }
80 }
81
82 $isNew = false;
83 try
84 {
85 if ($call)
86 {
87 if ($call->hasErrors())
88 {
89 $this->addErrors($call->getErrors());
90 Application::getConnection()->unlock($lockName);
91 return null;
92 }
93
94 if (!$call->getAssociatedEntity()->checkAccess($currentUserId))
95 {
96 if ($call instanceof \Bitrix\Call\Call\PlainCall)
97 {
98 $chat = ChatFactory::getInstance()->getPrivateChat($currentUserId, (int)$entityId);
99 if ($chat->getId() > 0)
100 {
101 $notifyService = NotifyService::getInstance();
102 $notifyService->sendOpponentBusyMessage($currentUserId, (int)$entityId);
103 }
104
105 $this->addError(new Error('User is currently busy on another call', 'user_is_busy'));
106 Application::getConnection()->unlock($lockName);
107 return null;
108 }
109
110 $this->addError(new Error('You can not access this call', 'access_denied'));
111 Application::getConnection()->unlock($lockName);
112 return null;
113 }
114
115 if (!$call->hasUser($currentUserId))
116 {
117 $addedUser = $call->addUser($currentUserId);
118
119 if (!$addedUser)
120 {
121 $this->addError(new Error("User limit reached", "user_limit_reached"));
122 Application::getConnection()->unlock($lockName);
123 return null;
124 }
125 }
126 }
127 else
128 {
129 $isNew = true;
130
131 try
132 {
133 $call = CallFactory::createWithEntity(
134 type: $type,
135 provider: $provider,
136 entityType: $entityType,
137 entityId: $entityId,
138 initiatorId: $currentUserId,
139 scheme: \Bitrix\Im\Call\Call::SCHEME_CLASSIC,
140 );
141 }
142 catch (\Throwable $e)
143 {
144 $this->addError(new Error($e->getMessage(), $e->getCode()));
145 Application::getConnection()->unlock($lockName);
146 return null;
147 }
148
149 if ($call->hasErrors())
150 {
151 $this->addErrors($call->getErrors());
152 Application::getConnection()->unlock($lockName);
153 return null;
154 }
155
156 if (!$call->getAssociatedEntity()->canStartCall($currentUserId))
157 {
158 $this->addError(new Error("You can not create this call", 'access_denied'));
159 Application::getConnection()->unlock($lockName);
160 return null;
161 }
162
163 $initiator = $call->getUser($currentUserId);
164 $initiator->update([
165 'STATE' => CallUser::STATE_READY,
166 'LAST_SEEN' => new DateTime(),
167 'FIRST_JOINED' => new DateTime()
168 ]);
169 }
170 }
171 catch(\Exception $e)
172 {
173 $this->addError(new Error(
174 "Can't initiate a call. Server error. (" . ($status ?? "") . ")",
175 "call_init_error")
176 );
177
178 Application::getConnection()->unlock($lockName);
179 return null;
180 }
181
182 Application::getConnection()->unlock($lockName);
183
184 return $this->formatCallResponse($call, 0, $isNew);
185 }
186
192 protected function formatCallResponse(\Bitrix\Im\Call\Call $call, int $initiatorId = 0, bool $isNew = false): array
193 {
194 $currentUserId = $this->getCurrentUser()->getId();
195
196 $users = $call->getUsers();
197 $publicChannels = Loader::includeModule('pull')
200 'USERS' => $users,
201 'JSON' => true
202 ])
203 : []
204 ;
205
206 $response = [
207 'call' => $call->toArray($initiatorId),
208 'connectionData' => $call->getConnectionData($currentUserId),
209 'users' => $users,
210 'userData' => $call->prepareUserData($users),
211 'publicChannels' => $publicChannels,
212 'logToken' => $call->getLogToken($currentUserId),
213 ];
214 if ($isNew)
215 {
216 $response['isNew'] = $isNew;
217 }
218 if (Settings::isAIServiceEnabled())
219 {
220 $response['ai'] = [
221 'serviceEnabled' => Settings::isAIServiceEnabled(),
222 'settingsEnabled' => CallAISettings::isEnableBySettings(),
223 'recordingMinUsers' => CallAISettings::getRecordMinUsers(),
224 'agreementAccepted' => CallAISettings::isAgreementAccepted(),
225 'tariffAvailable' => CallAISettings::isTariffAvailable(),
226 'baasAvailable' => CallAISettings::isBaasServiceHasPackage(),
227 ];
228 }
229
230 return $response;
231 }
232
240 public function createChildCallAction(int $parentId, string $newProvider, array $newUsers): ?array
241 {
242 $parentCall = Registry::getCallWithId($parentId);
243 if (!$parentCall)
244 {
245 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
246 return null;
247 }
248
249 $currentUserId = $this->getCurrentUser()->getId();
250 if (!$this->checkCallAccess($parentCall, $currentUserId))
251 {
252 $this->addError(new Error("You do not have access to the parent call", "access_denied"));
253 return null;
254 }
255
256 $childCall = $parentCall->makeClone($newProvider);
257 if ($childCall->hasErrors())
258 {
259 $this->addErrors($childCall->getErrors());
260 return null;
261 }
262
263 $initiator = $childCall->getUser($currentUserId);
264 $initiator->updateState(CallUser::STATE_READY);
265 $initiator->updateLastSeen(new DateTime());
266
267 foreach ($newUsers as $userId)
268 {
269 if (!$childCall->hasUser($userId))
270 {
271 $childCall->addUser($userId)?->updateState(CallUser::STATE_CALLING);
272 }
273 }
274
275 $users = $childCall->getUsers();
276
277 return [
278 'call' => $childCall->toArray(),
279 'connectionData' => $childCall->getConnectionData($currentUserId),
280 'users' => $users,
281 'userData' => $childCall->prepareUserData($users),
282 'logToken' => $childCall->getLogToken($currentUserId)
283 ];
284 }
285
294 public function tryJoinCallAction($type, $provider, $entityType, $entityId): ?array
295 {
296 $call = CallFactory::searchActive($type, $provider, $entityType, $entityId);
297 if (!$call)
298 {
299 return ['success' => false];
300 }
301
302 if ($call->hasErrors())
303 {
304 $this->addErrors($call->getErrors());
305 return null;
306 }
307
308 $currentUserId = $this->getCurrentUser()->getId();
309 if (!$call->getAssociatedEntity()->checkAccess($currentUserId))
310 {
311 $this->addError(new Error("You can not access this call", 'access_denied'));
312 return null;
313 }
314
315 if (!$call->hasUser($currentUserId))
316 {
317 $addedUser = $call->addUser($currentUserId);
318 if (!$addedUser)
319 {
320 $this->addError(new Error("User limit reached", "user_limit_reached"));
321 return null;
322 }
323 $call->getSignaling()->sendUsersJoined($currentUserId, [$currentUserId]);
324 }
325
326 return array_merge(
327 ['success' => true],
328 $this->formatCallResponse($call)
329 );
330 }
331
337 public function interruptAction(int $callId): ?array
338 {
339 $call = Registry::getCallWithId($callId);
340 if (!$call)
341 {
342 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
343 return null;
344 }
345
346 $currentUserId = $this->getCurrentUser()->getId();
347 if (!$this->checkCallAccess($call, $currentUserId))
348 {
349 $this->addError(new Error("You do not have access to the parent call", "access_denied"));
350 return null;
351 }
352
353 $call->setActionUserId($currentUserId)->finish();
354
355 return [
356 'call' => $call->toArray($currentUserId),
357 'connectionData' => $call->getConnectionData($currentUserId),
358 'logToken' => $call->getLogToken($currentUserId)
359 ];
360 }
361
367 public function getAction(int $callId): ?array
368 {
369 $call = Registry::getCallWithId($callId);
370 if (!$call)
371 {
372 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
373 return null;
374 }
375
376 $currentUserId = $this->getCurrentUser()->getId();
377 if (!$this->checkCallAccess($call, $currentUserId))
378 {
379 $this->addError(new Error("You do not have access to the parent call", "access_denied"));
380 return null;
381 }
382
383 return $this->formatCallResponse($call, $currentUserId);
384 }
385
396 public function inviteAction(int $callId, array $userIds, $video = "N", $show = "Y", $legacyMobile = "N", $repeated = "N"): ?bool
397 {
398 $isVideo = ($video === "Y");
399 $isShow = ($show === "Y");
400 $isLegacyMobile = ($legacyMobile === "Y");
401 $isRepeated = ($repeated === "Y");
402 $userIds = array_map('intVal', $userIds);
403
404 $call = Registry::getCallWithId($callId);
405 if (!$call)
406 {
407 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
408 return null;
409 }
410
411 $currentUserId = $this->getCurrentUser()->getId();
412 if (!$this->checkCallAccess($call, $currentUserId))
413 {
414 return null;
415 }
416
417 if ($call->hasErrors())
418 {
419 $this->addErrors($call->getErrors());
420 return null;
421 }
422
423 $call->getUser($currentUserId)->update([
424 'LAST_SEEN' => new DateTime(),
425 'IS_MOBILE' => ($isLegacyMobile ? 'Y' : 'N')
426 ]);
427
428 $lockName = static::getLockNameWithCallId('invite', $callId);
429 if (!Application::getConnection()->lock($lockName, static::LOCK_TTL))
430 {
431 $this->addError(new Error("Could not get exclusive lock", "could_not_lock"));
432 return null;
433 }
434
435 $this->inviteUsers($call, $userIds, $isLegacyMobile, $isVideo, $isShow, $isRepeated);
436
437 Application::getConnection()->unlock($lockName);
438
439 return true;
440 }
441
442 protected function inviteUsers(\Bitrix\Im\Call\Call $call, $userIds, $isLegacyMobile, $isVideo, $isShow, $isRepeated): void
443 {
444 $usersToInvite = [];
445 $existingUsers = [];
446 foreach ($userIds as $userId)
447 {
448 $userId = (int)$userId;
449 if (!$userId)
450 {
451 continue;
452 }
453 if (!$call->hasUser($userId))
454 {
455 if (!$call->addUser($userId))
456 {
457 continue;
458 }
459 }
460 else if ($isRepeated === false && $call->getAssociatedEntity())
461 {
462 $existingUsers[] = $userId;
463 }
464 $usersToInvite[] = $userId;
465 $callUser = $call->getUser($userId);
466 if($callUser->getState() != CallUser::STATE_READY)
467 {
468 $callUser->updateState(CallUser::STATE_CALLING);
469 }
470 }
471
472 if (!empty($existingUsers))
473 {
474 $call->getAssociatedEntity()->onExistingUsersInvite($existingUsers);
475 }
476
477 if (count($usersToInvite) === 0)
478 {
479 $this->addError(new Error("No users to invite", "empty_users"));
480 return;
481 }
482
483 $sendPush = $isRepeated !== true;
484
485 // send invite to the ones being invited.
486 $call->inviteUsers(
487 $this->getCurrentUser()->getId(),
488 $usersToInvite,
489 $isLegacyMobile,
490 $isVideo,
491 $sendPush
492 );
493
494 // send userInvited to everyone else.
495 $allUsers = $call->getUsers();
496 $otherUsers = array_diff($allUsers, $userIds);
497 $call->getSignaling()->sendUsersInvited(
498 $this->getCurrentUser()->getId(),
499 $otherUsers,
500 $usersToInvite,
501 $isShow
502 );
503
504 if ($call->getState() === \Bitrix\Im\Call\Call::STATE_NEW)
505 {
506 $call->updateState(\Bitrix\Im\Call\Call::STATE_INVITING);
507 }
508 }
509
515 public function cancelAction(int $callId)
516 {
517 $call = Registry::getCallWithId($callId);
518 if (!$call)
519 {
520 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
521 return null;
522 }
523
524 $currentUserId = $this->getCurrentUser()->getId();
525 if (!$this->checkCallAccess($call, $currentUserId))
526 {
527 return null;
528 }
529 }
530
538 public function answerAction(int $callId, $callInstanceId, $legacyMobile = "N")
539 {
540 $isLegacyMobile = $legacyMobile === "Y";
541 $call = Registry::getCallWithId($callId);
542 if (!$call)
543 {
544 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
545 return null;
546 }
547
548 $currentUserId = $this->getCurrentUser()->getId();
549 if (!$this->checkCallAccess($call, $currentUserId))
550 {
551 return null;
552 }
553
554 $callUser = $call->getUser($currentUserId);
555 if ($callUser)
556 {
557 $lockName = static::getLockNameWithCallId('user'.$currentUserId, $callId);
558 if (!Application::getConnection()->lock($lockName, static::LOCK_TTL))
559 {
560 $this->addError(new Error("Could not get exclusive lock", "could_not_lock"));
561 return null;
562 }
563
564 $callUser->update([
565 'STATE' => CallUser::STATE_READY,
566 'LAST_SEEN' => new DateTime(),
567 'FIRST_JOINED' => $callUser->getFirstJoined() ?: new DateTime(),
568 'IS_MOBILE' => $isLegacyMobile ? 'Y' : 'N',
569 ]);
570
571 Application::getConnection()->unlock($lockName);
572 }
573
574 $call->getSignaling()->sendAnswer($currentUserId, $callInstanceId, $isLegacyMobile);
575 }
576
584 public function declineAction(int $callId, $callInstanceId, int $code = 603)
585 {
586 $currentUserId = $this->getCurrentUser()->getId();
587 $call = Registry::getCallWithId($callId);
588 if (!$call)
589 {
590 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
591 return null;
592 }
593
594 if (!$this->checkCallAccess($call, $currentUserId))
595 {
596 return null;
597 }
598
599 $callUser = $call->getUser($currentUserId);
600 if (!$callUser)
601 {
602 $this->addError(new Error("User is not part of the call", "unknown_call_user"));
603 return null;
604 }
605
606 if ($callUser->getState() === CallUser::STATE_READY)
607 {
608 $this->addError(new Error("Can not decline in {$callUser->getState()} user state", "wrong_user_state"));
609 return null;
610 }
611
612 $lockName = static::getLockNameWithCallId('user'.$currentUserId, $callId);
613 if (!Application::getConnection()->lock($lockName, static::LOCK_TTL))
614 {
615 $this->addError(new Error("Could not get exclusive lock", "could_not_lock"));
616 return null;
617 }
618
619 if ($code === 486)
620 {
621 $callUser->updateState(CallUser::STATE_BUSY);
622 }
623 else
624 {
625 $callUser->updateState(CallUser::STATE_DECLINED);
626 }
627 $callUser->updateLastSeen(new DateTime());
628
629 Application::getConnection()->unlock($lockName);
630
631 $userIds = $call->getUsers();
632 $call->getSignaling()->sendHangup($currentUserId, $userIds, $callInstanceId, $code);
633
634 if (!$call->hasActiveUsers())
635 {
636 $call->setActionUserId($currentUserId)->finish();
637 }
638 }
639
647 public function pingAction(int $callId, $requestId, $retransmit = true)
648 {
649 $call = Registry::getCallWithId($callId);
650 if (!$call)
651 {
652 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
653 return null;
654 }
655
656 $currentUserId = $this->getCurrentUser()->getId();
657 if (!$this->checkCallAccess($call, $currentUserId))
658 {
659 return null;
660 }
661
662 $callUser = $call->getUser($currentUserId);
663 if ($callUser)
664 {
665 $callUser->updateLastSeen(new DateTime());
666 if ($callUser->getState() == CallUser::STATE_UNAVAILABLE)
667 {
668 $callUser->updateState(CallUser::STATE_IDLE);
669 }
670 }
671
672 if (
673 is_bool($retransmit) && $retransmit===true
674 || is_string($retransmit) && in_array($retransmit, ['true', 'Y', '1'], true)
675 )
676 {
677 $call->getSignaling()->sendPing($currentUserId, $requestId);
678 }
679
680 return true;
681 }
682
688 public function onShareScreenAction(int $callId)
689 {
690 $call = Registry::getCallWithId($callId);
691 if (!$call)
692 {
693 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
694 return null;
695 }
696
697 $currentUserId = $this->getCurrentUser()->getId();
698 if (!$this->checkCallAccess($call, $currentUserId))
699 {
700 return null;
701 }
702
703 $callUser = $call->getUser($currentUserId);
704 if ($callUser)
705 {
706 $callUser->update([
707 'SHARED_SCREEN' => 'Y'
708 ]);
709 }
710 }
711
717 public function onStartRecordAction(int $callId)
718 {
719 $call = Registry::getCallWithId($callId);
720 if (!$call)
721 {
722 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
723 return null;
724 }
725
726 $currentUserId = $this->getCurrentUser()->getId();
727 if (!$this->checkCallAccess($call, $currentUserId))
728 {
729 return null;
730 }
731
732 $callUser = $call->getUser($currentUserId);
733 if ($callUser)
734 {
735 $callUser->update([
736 'RECORDED' => 'Y'
737 ]);
738 }
739 }
740
748 public function negotiationNeededAction(int $callId, int $userId, $restart = false)
749 {
750 $restart = (bool)$restart;
751 $call = Registry::getCallWithId($callId);
752 if (!$call)
753 {
754 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
755 return null;
756 }
757
758 $currentUserId = $this->getCurrentUser()->getId();
759 if (!$this->checkCallAccess($call, $currentUserId))
760 {
761 return null;
762 }
763
764 $callUser = $call->getUser($currentUserId);
765 if ($callUser)
766 {
767 $callUser->updateLastSeen(new DateTime());
768 }
769
770 $call->getSignaling()->sendNegotiationNeeded($currentUserId, $userId, $restart);
771 }
772
782 public function connectionOfferAction(int $callId, int $userId, $connectionId, $sdp, $userAgent)
783 {
784 $call = Registry::getCallWithId($callId);
785 if (!$call)
786 {
787 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
788 return null;
789 }
790
791 $currentUserId = $this->getCurrentUser()->getId();
792 if (!$this->checkCallAccess($call, $currentUserId))
793 {
794 return null;
795 }
796
797 $callUser = $call->getUser($currentUserId);
798 if ($callUser)
799 {
800 $callUser->updateLastSeen(new DateTime());
801 }
802
803 $call->getSignaling()->sendConnectionOffer($currentUserId, $userId, $connectionId, $sdp, $userAgent);
804 }
805
815 public function connectionAnswerAction(int $callId, int $userId, $connectionId, $sdp, $userAgent)
816 {
817 $currentUserId = $this->getCurrentUser()->getId();
818 $call = Registry::getCallWithId($callId);
819 if (!$call)
820 {
821 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
822 return null;
823 }
824
825 if (!$this->checkCallAccess($call, $currentUserId))
826 {
827 return null;
828 }
829
830 $callUser = $call->getUser($currentUserId);
831 if ($callUser)
832 {
833 $callUser->updateLastSeen(new DateTime());
834 }
835
836 $call->getSignaling()->sendConnectionAnswer($currentUserId, $userId, $connectionId, $sdp, $userAgent);
837 }
838
847 public function iceCandidateAction(int $callId, int $userId, $connectionId, array $candidates)
848 {
849 // mobile can alter key order, so we recover it
850 ksort($candidates);
851
852 $currentUserId = $this->getCurrentUser()->getId();
853 $call = Registry::getCallWithId($callId);
854
855 if (!$this->checkCallAccess($call, $currentUserId))
856 {
857 return null;
858 }
859
860 $callUser = $call->getUser($currentUserId);
861 if ($callUser)
862 {
863 $callUser->updateLastSeen(new DateTime());
864 }
865
866 $call->getSignaling()->sendIceCandidates($currentUserId, $userId, $connectionId, $candidates);
867 }
868
876 public function hangupAction(int $callId, $callInstanceId, $retransmit = true)
877 {
878 $call = Registry::getCallWithId($callId);
879 if (!$call)
880 {
881 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
882 return null;
883 }
884
885 $currentUserId = $this->getCurrentUser()->getId();
886 if (!$this->checkCallAccess($call, $currentUserId))
887 {
888 return null;
889 }
890
891 $lockName = static::getLockNameWithCallId('user'.$currentUserId, $callId);
892 if (!Application::getConnection()->lock($lockName, static::LOCK_TTL))
893 {
894 $this->addError(new Error("Could not get exclusive lock", "could_not_lock"));
895 return null;
896 }
897
898 $callUser = $call->getUser($currentUserId);
899 if ($callUser)
900 {
901 $callUser->updateState(CallUser::STATE_IDLE);
902 $callUser->updateLastSeen(new DateTime());
903 }
904
905 if (
906 is_bool($retransmit) && $retransmit===true
907 || is_string($retransmit) && in_array($retransmit, ['true', 'Y', '1'], true)
908 )
909 {
910 $userIds = $call->getUsers();
911 $call->getSignaling()->sendHangup($currentUserId, $userIds, $callInstanceId);
912 }
913
914 Application::getConnection()->unlock($lockName);
915
916 if (!$call->hasActiveUsers())
917 {
918 $call->setActionUserId($currentUserId)->finish();
919 }
920 }
921
927 public function finishAction(int $callId): ?array
928 {
929 $call = Registry::getCallWithId($callId);
930 if (!$call)
931 {
932 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
933 return null;
934 }
935 $currentUserId = $this->getCurrentUser()->getId();
936 if (!$this->checkCallAccess($call, $currentUserId))
937 {
938 $this->addError(new Error("You do not have access to the parent call", "access_denied"));
939 return null;
940 }
941
942 $call->setActionUserId($currentUserId)->finish();
943
944 return [
945 'call' => $call->toArray($currentUserId),
946 'connectionData' => $call->getConnectionData($currentUserId),
947 'logToken' => $call->getLogToken($currentUserId)
948 ];
949 }
950
957 public function getUsersAction(int $callId, array $userIds = [])
958 {
959 $call = Registry::getCallWithId($callId);
960 if (!$call)
961 {
962 $this->addError(new Error(Loc::getMessage("IM_REST_CALL_ERROR_CALL_NOT_FOUND"), "call_not_found"));
963 return null;
964 }
965
966 $currentUserId = $this->getCurrentUser()->getId();
967 if (!$this->checkCallAccess($call, $currentUserId))
968 {
969 $this->addError(new Error("You do not have access to the call", "access_denied"));
970 return null;
971 }
972
973 if (empty($userIds))
974 {
975 $allowedUserIds = $call->getUsers();
976 }
977 else
978 {
979 $allowedUserIds = array_filter($userIds, function($userId) use ($call, $currentUserId)
980 {
981 return $userId == $currentUserId || $call->hasUser($userId);
982 });
983 }
984
985 if (empty($allowedUserIds))
986 {
987 $this->addError(new Error("Users are not part of the call", "access_denied"));
988 return null;
989 }
990
991 return $call->prepareUserData($allowedUserIds);
992 }
993
1000 public function getUserStateAction(int $callId, int $userId = 0)
1001 {
1002 $currentUserId = (int)$this->getCurrentUser()->getId();
1003 $call = Registry::getCallWithId($callId);
1004
1005 if (!$call || !$this->checkCallAccess($call, $currentUserId))
1006 {
1007 $this->addError(new Error("Call is not found or you do not have access to the call", "access_denied"));
1008 return null;
1009 }
1010
1011 if ($userId === 0)
1012 {
1013 $userId = $currentUserId;
1014 }
1015
1016 $callUser = $call->getUser($userId);
1017 if (!$callUser)
1018 {
1019 $this->addError(new Error("User is not part of the call", "unknown_call_user"));
1020 return null;
1021 }
1022
1023 return $callUser->toArray();
1024 }
1025
1030 public function getCallLimitsAction(): array
1031 {
1032 return [
1033 'callServerEnabled' => \Bitrix\Im\Call\Call::isCallServerEnabled(),
1034 'maxParticipants' => \Bitrix\Im\Call\Call::getMaxParticipants(),
1035 ];
1036 }
1037
1044 public function reportConnectionStatusAction(int $callId, bool $connectionStatus): void
1045 {
1046 AddEventToStatFile('im', 'call_connection', $callId, ($connectionStatus ? 'Y' : 'N'));
1047 }
1048
1049 protected function checkCallAccess(\Bitrix\Im\Call\Call $call, $userId)
1050 {
1051 if (!$call->checkAccess($userId))
1052 {
1053 $this->addError(new Error("You don't have access to the call " . $call->getId() . "; (current user id: " . $userId . ")", 'access_denied'));
1054 return false;
1055 }
1056
1057 return true;
1058 }
1059
1060 protected static function getLockNameWithEntityId(string $entityType, $entityId, $currentUserId): string
1061 {
1062 if ($entityType === EntityType::CHAT && (Common::isChatId($entityId) || (int)$entityId > 0))
1063 {
1064 $chatId = \Bitrix\Im\Dialog::getChatId($entityId, $currentUserId);
1065
1066 return "call_entity_{$entityType}_{$chatId}";
1067 }
1068
1069 return "call_entity_{$entityType}_{$entityId}";
1070 }
1071
1072 protected static function getLockNameWithCallId(string $prefix, $callId): string
1073 {
1074 //TODO: int|string after switching to php 8
1075 if (is_string($callId) || is_numeric($callId))
1076 {
1077 return "{$prefix}_call_{$callId}";
1078 }
1079
1080 return '';
1081 }
1082
1083 public function configureActions(): array
1084 {
1085 return [
1086 'getUsers' => [
1087 '+prefilters' => [new Engine\ActionFilter\CloseSession()],
1088 ],
1089 'reportConnectionStatus' => [
1090 '+prefilters' => [new Engine\ActionFilter\CloseSession()],
1091 ],
1092 ];
1093 }
1094}
$type
Определения options.php:106
if(!Loader::includeModule('messageservice')) $provider
Определения callback_ednaruimhpx.php:21
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static getMaxParticipants()
Определения call.php:1076
static isCallServerEnabled()
Определения call.php:1331
static getCallWithId(int $id)
Определения registry.php:17
Определения util.php:6
Определения common.php:7
static isChatId($id)
Определения common.php:58
pingAction(int $callId, $requestId, $retransmit=true)
Определения call.php:647
connectionAnswerAction(int $callId, int $userId, $connectionId, $sdp, $userAgent)
Определения call.php:815
getCallLimitsAction()
Определения call.php:1030
static getLockNameWithCallId(string $prefix, $callId)
Определения call.php:1072
const LOCK_TTL
Определения call.php:25
iceCandidateAction(int $callId, int $userId, $connectionId, array $candidates)
Определения call.php:847
negotiationNeededAction(int $callId, int $userId, $restart=false)
Определения call.php:748
tryJoinCallAction($type, $provider, $entityType, $entityId)
Определения call.php:294
connectionOfferAction(int $callId, int $userId, $connectionId, $sdp, $userAgent)
Определения call.php:782
getUserStateAction(int $callId, int $userId=0)
Определения call.php:1000
inviteAction(int $callId, array $userIds, $video="N", $show="Y", $legacyMobile="N", $repeated="N")
Определения call.php:396
cancelAction(int $callId)
Определения call.php:515
hangupAction(int $callId, $callInstanceId, $retransmit=true)
Определения call.php:876
getUsersAction(int $callId, array $userIds=[])
Определения call.php:957
createChildCallAction(int $parentId, string $newProvider, array $newUsers)
Определения call.php:240
checkCallAccess(\Bitrix\Im\Call\Call $call, $userId)
Определения call.php:1049
interruptAction(int $callId)
Определения call.php:337
getAction(int $callId)
Определения call.php:367
onStartRecordAction(int $callId)
Определения call.php:717
onShareScreenAction(int $callId)
Определения call.php:688
inviteUsers(\Bitrix\Im\Call\Call $call, $userIds, $isLegacyMobile, $isVideo, $isShow, $isRepeated)
Определения call.php:442
configureActions()
Определения call.php:1083
static getLockNameWithEntityId(string $entityType, $entityId, $currentUserId)
Определения call.php:1060
answerAction(int $callId, $callInstanceId, $legacyMobile="N")
Определения call.php:538
reportConnectionStatusAction(int $callId, bool $connectionStatus)
Определения call.php:1044
finishAction(int $callId)
Определения call.php:927
createAction(int $type, string $provider, string $entityType, string $entityId, bool $joinExisting=false)
Определения call.php:37
formatCallResponse(\Bitrix\Im\Call\Call $call, int $initiatorId=0, bool $isNew=false)
Определения call.php:192
declineAction(int $callId, $callInstanceId, int $code=603)
Определения call.php:584
static getChatId($dialogId, $userId=null)
Определения dialog.php:93
addError(Error $error)
Определения controller.php:1070
addErrors(array $errors)
Определения controller.php:1083
Определения error.php:15
Определения loader.php:13
static getPublicIds($params=[])
Определения channel.php:25
const TYPE_PRIVATE
Определения pull_channel.php:9
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
$status
Определения session.php:10
AddEventToStatFile($module, $action, $tag, $label, $action_type='', $user_id=null)
Определения tools.php:3976
Определения call.php:3
Определения action.php:3
$entityId
Определения payment.php:4
</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
$response
Определения result.php:21