UPSTREAM BASELINE: nextcloud/spreed v22.0.12 (без изменений)
Type checking / changes (push) Has been cancelled
Type checking / test (push) Has been cancelled
Type checking / typescript-summary (push) Has been cancelled
Node tests / changes (push) Has been cancelled
Node tests / test (push) Has been cancelled
Node tests / test-summary (push) Has been cancelled

Источник: https://github.com/nextcloud/spreed/archive/refs/tags/v22.0.12.tar.gz
С этого коммита ветка официального Nextcloud Talk отрезана (решение владельца 2026-07-06).
Все дальнейшие изменения — только наши; версии релизов: 22.0.12-f7.N.
This commit is contained in:
2026-07-06 14:07:50 +00:00
commit 01acfa3b40
1716 changed files with 613013 additions and 0 deletions
+699
View File
@@ -0,0 +1,699 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Talk\Chat\SystemMessage;
use DateInterval;
use OCA\Talk\Chat\ChatManager;
use OCA\Talk\Chat\MessageParser;
use OCA\Talk\Events\AAttendeeRemovedEvent;
use OCA\Talk\Events\AParticipantModifiedEvent;
use OCA\Talk\Events\ARoomEvent;
use OCA\Talk\Events\ARoomModifiedEvent;
use OCA\Talk\Events\AttendeeRemovedEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Events\AttendeesRemovedEvent;
use OCA\Talk\Events\BeforeDuplicateShareSentEvent;
use OCA\Talk\Events\BeforeParticipantModifiedEvent;
use OCA\Talk\Events\LobbyModifiedEvent;
use OCA\Talk\Events\ParticipantModifiedEvent;
use OCA\Talk\Events\RoomCreatedEvent;
use OCA\Talk\Events\RoomModifiedEvent;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\BreakoutRoom;
use OCA\Talk\Model\Message;
use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCA\Talk\Service\NoteToSelfService;
use OCA\Talk\Service\ParticipantService;
use OCA\Talk\Service\SampleConversationsService;
use OCA\Talk\Service\ThreadService;
use OCA\Talk\TalkSession;
use OCA\Talk\Webinary;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Comments\IComment;
use OCP\Comments\NotFoundException;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IL10N;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\Events\BeforeShareCreatedEvent;
use OCP\Share\Events\ShareCreatedEvent;
use OCP\Share\IShare;
use Psr\Log\LoggerInterface;
/**
* @template-implements IEventListener<Event>
*/
class Listener implements IEventListener {
public function __construct(
protected IRequest $request,
protected ChatManager $chatManager,
protected TalkSession $talkSession,
protected ISession $session,
protected IUserSession $userSession,
protected ITimeFactory $timeFactory,
protected Manager $manager,
protected ParticipantService $participantService,
protected MessageParser $messageParser,
protected ThreadService $threadService,
protected IL10N $l,
protected LoggerInterface $logger,
) {
}
#[\Override]
public function handle(Event $event): void {
if ($event instanceof ARoomEvent && $event->getRoom()->isFederatedConversation()) {
return;
}
if ($event instanceof AttendeesAddedEvent) {
$this->attendeesAddedEvent($event);
} elseif ($event instanceof AttendeeRemovedEvent) {
$this->sendSystemMessageUserRemoved($event);
} elseif ($event instanceof AttendeesRemovedEvent) {
$this->attendeesRemovedEvent($event);
} elseif ($event instanceof RoomCreatedEvent) {
$this->sendSystemMessageAboutConversationCreated($event);
} elseif ($event instanceof LobbyModifiedEvent) {
$this->sendSystemLobbyMessage($event);
} elseif ($event instanceof RoomModifiedEvent) {
match ($event->getProperty()) {
ARoomModifiedEvent::PROPERTY_AVATAR => $this->avatarChanged($event),
ARoomModifiedEvent::PROPERTY_CALL_RECORDING => $this->setCallRecording($event),
ARoomModifiedEvent::PROPERTY_DESCRIPTION => $this->sendSystemMessageAboutRoomDescriptionChanges($event),
ARoomModifiedEvent::PROPERTY_LISTABLE => $this->sendSystemListableMessage($event),
ARoomModifiedEvent::PROPERTY_MESSAGE_EXPIRATION => $this->afterSetMessageExpiration($event),
ARoomModifiedEvent::PROPERTY_NAME => $this->sendSystemMessageAboutConversationRenamed($event),
ARoomModifiedEvent::PROPERTY_PASSWORD => $this->sendSystemMessageAboutRoomPassword($event),
ARoomModifiedEvent::PROPERTY_READ_ONLY => $this->sendSystemReadOnlyMessage($event),
ARoomModifiedEvent::PROPERTY_TYPE => $this->sendSystemGuestPermissionsMessage($event),
default => null,
};
} elseif ($event instanceof BeforeParticipantModifiedEvent) {
match ($event->getProperty()) {
AParticipantModifiedEvent::PROPERTY_IN_CALL => $this->sendSystemMessageAboutBeginOfCall($event),
default => null,
};
} elseif ($event instanceof ParticipantModifiedEvent) {
match ($event->getProperty()) {
AParticipantModifiedEvent::PROPERTY_TYPE => $this->sendSystemMessageAboutPromoteOrDemoteModerator($event),
AParticipantModifiedEvent::PROPERTY_IN_CALL => $this->sendSystemMessageAboutCallLeft($event),
default => null,
};
} elseif ($event instanceof BeforeShareCreatedEvent) {
$this->setShareExpiration($event);
} elseif ($event instanceof BeforeDuplicateShareSentEvent || $event instanceof ShareCreatedEvent) {
$this->fixMimeTypeOfVoiceMessage($event);
}
}
protected function sendSystemMessageAboutBeginOfCall(BeforeParticipantModifiedEvent $event): void {
if ($event->getOldValue() !== Participant::FLAG_DISCONNECTED
|| $event->getNewValue() === Participant::FLAG_DISCONNECTED) {
return;
}
if ($this->participantService->hasActiveSessionsInCall($event->getRoom())) {
$this->sendSystemMessage($event->getRoom(), 'call_joined', [], $event->getParticipant());
} else {
$silent = $event->getDetail(AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT) ?? false;
$this->sendSystemMessage($event->getRoom(), 'call_started', [], $event->getParticipant(), silent: $silent);
}
}
protected function sendSystemMessageAboutCallLeft(ParticipantModifiedEvent $event): void {
if ($event->getDetail(AParticipantModifiedEvent::DETAIL_IN_CALL_END_FOR_EVERYONE)) {
// No individual system message if the call is ended for everyone
return;
}
if ($event->getNewValue() === $event->getOldValue()) {
return;
}
if ($event->getOldValue() === Participant::FLAG_DISCONNECTED
|| $event->getNewValue() !== Participant::FLAG_DISCONNECTED) {
return;
}
$session = $event->getParticipant()->getSession();
if (!$session instanceof Session) {
// This happens in case the user was kicked/lobbied
return;
}
$this->sendSystemMessage($event->getRoom(), 'call_left', [], $event->getParticipant());
}
protected function sendSystemMessageAboutConversationCreated(RoomCreatedEvent $event): void {
if ($event->getRoom()->getType() === Room::TYPE_CHANGELOG || $this->isCreatingNoteToSelfAutomatically($event) || $this->isCreatingSample($event)) {
$this->sendSystemMessage($event->getRoom(), 'conversation_created', forceSystemAsActor: true);
} else {
$this->sendSystemMessage($event->getRoom(), 'conversation_created');
}
}
protected function sendSystemMessageAboutConversationRenamed(RoomModifiedEvent $event): void {
if ($event->getOldValue() === ''
|| $event->getNewValue() === '') {
return;
}
$this->sendSystemMessage($event->getRoom(), 'conversation_renamed', [
'newName' => $event->getNewValue(),
'oldName' => $event->getOldValue(),
]);
}
protected function sendSystemMessageAboutRoomDescriptionChanges(RoomModifiedEvent $event): void {
if ($event->getNewValue() !== '') {
if ($this->isCreatingNoteToSelf($event) || $this->isCreatingSample($event)) {
return;
}
$this->sendSystemMessage($event->getRoom(), 'description_set', [
'newDescription' => $event->getNewValue(),
]);
} else {
$this->sendSystemMessage($event->getRoom(), 'description_removed');
}
}
protected function sendSystemMessageAboutRoomPassword(RoomModifiedEvent $event): void {
if ($event->getNewValue() !== '') {
$this->sendSystemMessage($event->getRoom(), 'password_set');
} else {
$this->sendSystemMessage($event->getRoom(), 'password_removed');
}
}
protected function sendSystemGuestPermissionsMessage(RoomModifiedEvent $event): void {
if ($event->getOldValue() === Room::TYPE_ONE_TO_ONE) {
return;
}
if ($event->getNewValue() === Room::TYPE_PUBLIC) {
$this->sendSystemMessage($event->getRoom(), 'guests_allowed');
} elseif ($event->getNewValue() === Room::TYPE_GROUP) {
$this->sendSystemMessage($event->getRoom(), 'guests_disallowed');
}
}
protected function sendSystemReadOnlyMessage(RoomModifiedEvent $event): void {
$room = $event->getRoom();
if ($room->getType() === Room::TYPE_CHANGELOG) {
return;
}
if ($event->getNewValue() === Room::READ_ONLY) {
$this->sendSystemMessage($room, 'read_only');
} elseif ($event->getNewValue() === Room::READ_WRITE) {
$this->sendSystemMessage($room, 'read_only_off');
}
}
protected function sendSystemListableMessage(RoomModifiedEvent $event): void {
if ($event->getNewValue() === Room::LISTABLE_NONE) {
$this->sendSystemMessage($event->getRoom(), 'listable_none');
} elseif ($event->getNewValue() === Room::LISTABLE_USERS) {
$this->sendSystemMessage($event->getRoom(), 'listable_users');
} elseif ($event->getNewValue() === Room::LISTABLE_ALL) {
$this->sendSystemMessage($event->getRoom(), 'listable_all');
}
}
protected function sendSystemLobbyMessage(LobbyModifiedEvent $event): void {
if ($event->getNewValue() === $event->getOldValue()) {
return;
}
$room = $event->getRoom();
if ($room->getObjectType() === BreakoutRoom::PARENT_OBJECT_TYPE) {
if ($event->getNewValue() === Webinary::LOBBY_NONE) {
$this->sendSystemMessage($room, 'breakout_rooms_started');
} else {
$this->sendSystemMessage($room, 'breakout_rooms_stopped');
}
} elseif ($event->isTimerReached()) {
$this->sendSystemMessage($room, 'lobby_timer_reached');
} elseif ($event->getNewValue() === Webinary::LOBBY_NONE) {
$this->sendSystemMessage($room, 'lobby_none');
} elseif ($event->getNewValue() === Webinary::LOBBY_NON_MODERATORS) {
$this->sendSystemMessage($room, 'lobby_non_moderators');
}
}
protected function addSystemMessageUserAdded(AttendeesAddedEvent $event, Attendee $attendee): void {
$room = $event->getRoom();
if ($room->getType() === Room::TYPE_ONE_TO_ONE) {
return;
}
if ($room->getType() === Room::TYPE_CHANGELOG) {
return;
}
$userJoinedFileRoom = $room->getObjectType() === Room::OBJECT_TYPE_FILE && $attendee->getParticipantType() !== Participant::USER_SELF_JOINED;
// add a message "X joined the conversation", whenever user $userId:
if (
// - has joined a file room but not through a public link
$userJoinedFileRoom
// - has been added by another user (and not when creating a conversation)
|| $this->getUserId() !== $attendee->getActorId()
// - has joined a listable room on their own
|| $attendee->getParticipantType() === Participant::USER) {
$this->logger->debug('User "' . $attendee->getActorId() . '" added to room "' . $room->getToken() . '"', ['app' => 'spreed-bfp']);
$comment = $this->sendSystemMessage(
$room,
'user_added',
['user' => $attendee->getActorId()],
null,
$event->shouldSkipLastMessageUpdate()
);
$event->setLastMessage($comment);
}
}
protected function sendSystemMessageUserRemoved(AttendeeRemovedEvent $event): void {
$room = $event->getRoom();
if ($event->getAttendee()->getActorType() !== Attendee::ACTOR_USERS) {
return;
}
if ($room->getType() === Room::TYPE_ONE_TO_ONE) {
return;
}
if ($event->getReason() === AAttendeeRemovedEvent::REASON_LEFT
&& $event->getAttendee()->getParticipantType() === Participant::USER_SELF_JOINED) {
// Self-joined user closes the tab/window or leaves via the menu
return;
}
$this->logger->debug('User "' . $event->getAttendee()->getActorId() . '" removed from room "' . $room->getToken() . '"', ['app' => 'spreed-bfp']);
$this->sendSystemMessage($room, 'user_removed', ['user' => $event->getAttendee()->getActorId()]);
}
public function sendSystemMessageAboutPromoteOrDemoteModerator(ParticipantModifiedEvent $event): void {
$room = $event->getRoom();
$attendee = $event->getParticipant()->getAttendee();
if (!in_array($attendee->getActorType(), [
Attendee::ACTOR_USERS,
Attendee::ACTOR_EMAILS,
Attendee::ACTOR_GUESTS,
], true)) {
return;
}
if ($event->getNewValue() === Participant::MODERATOR) {
$this->sendSystemMessage($room, 'moderator_promoted', ['user' => $attendee->getActorId()]);
} elseif ($event->getNewValue() === Participant::USER) {
if ($event->getOldValue() === Participant::USER_SELF_JOINED) {
$this->sendSystemMessage($room, 'user_added', ['user' => $attendee->getActorId()]);
} else {
$this->sendSystemMessage($room, 'moderator_demoted', ['user' => $attendee->getActorId()]);
}
} elseif ($event->getNewValue() === Participant::GUEST_MODERATOR) {
$this->sendSystemMessage($room, 'guest_moderator_promoted', ['type' => $attendee->getActorType(), 'id' => $attendee->getActorId()]);
} elseif ($event->getNewValue() === Participant::GUEST) {
$this->sendSystemMessage($room, 'guest_moderator_demoted', ['type' => $attendee->getActorType(), 'id' => $attendee->getActorId()]);
}
}
protected function setShareExpiration(BeforeShareCreatedEvent $event): void {
$share = $event->getShare();
if ($share->getShareType() !== IShare::TYPE_ROOM) {
return;
}
$room = $this->manager->getRoomByToken($share->getSharedWith());
$messageExpiration = $room->getMessageExpiration();
if (!$messageExpiration) {
return;
}
$dateTime = $this->timeFactory->getDateTime();
$dateTime->add(DateInterval::createFromDateString($messageExpiration . ' seconds'));
$share->setExpirationDate($dateTime);
}
protected function fixMimeTypeOfVoiceMessage(ShareCreatedEvent|BeforeDuplicateShareSentEvent $event): void {
$share = $event->getShare();
if ($share->getShareType() !== IShare::TYPE_ROOM) {
return;
}
if (strtolower($this->request->getParam('_route')) === 'ocs.spreed.recording.sharetochat') {
return;
}
$room = $this->manager->getRoomByToken($share->getSharedWith());
$this->participantService->ensureOneToOneRoomIsFilled($room);
$metaData = $this->request->getParam('talkMetaData') ?? '';
$metaData = json_decode($metaData, true);
$metaData = is_array($metaData) ? $metaData : [];
if (isset($metaData['messageType']) && $metaData['messageType'] === ChatManager::VERB_VOICE_MESSAGE) {
if ($share->getNode()->getMimeType() !== 'audio/mpeg'
&& $share->getNode()->getMimeType() !== 'audio/wav') {
unset($metaData['messageType']);
}
}
$metaData['mimeType'] = $share->getNode()->getMimeType();
if (isset($metaData['caption'])) {
if (is_string($metaData['caption']) && trim($metaData['caption']) !== '') {
$metaData['caption'] = trim($metaData['caption']);
} else {
unset($metaData['caption']);
}
}
if (isset($metaData[Message::METADATA_SILENT])) {
$silent = (bool)$metaData[Message::METADATA_SILENT];
} else {
$silent = false;
}
$replyTo = null;
if (isset($metaData['replyTo'])) {
$replyTo = (int)$metaData['replyTo'];
unset($metaData['replyTo']);
}
$threadId = null;
if (isset($metaData['threadId'])) {
$threadId = (int)$metaData['threadId'];
unset($metaData['threadId']);
}
$threadTitle = '';
if (isset($metaData['threadTitle'])) {
if (is_string($metaData['threadTitle']) && trim($metaData['threadTitle']) !== '') {
$threadTitle = trim($metaData['threadTitle']);
}
unset($metaData['threadTitle']);
}
$comment = $this->sendSystemMessage(
$room,
'file_shared',
['share' => $share->getId(), 'metaData' => $metaData],
silent: $silent,
replyTo: $replyTo,
threadId: $threadId,
);
$messageId = (int)$comment->getId();
if ($threadTitle !== '' && $comment->getTopmostParentId() === '0') {
$thread = $this->threadService->createThread($room, $messageId, $threadTitle);
try {
// Add to subscribed threads list
$participant = $this->participantService->getParticipant($room, $this->getUserId());
$this->threadService->setNotificationLevel($participant->getAttendee(), $thread->getId(), Participant::NOTIFY_DEFAULT);
} catch (ParticipantNotFoundException) {
}
$this->sendSystemMessage(
$room,
'thread_created',
['thread' => $messageId, 'title' => $thread->getName()],
shouldSkipLastMessageUpdate: true,
silent: true,
parent: $comment,
);
}
}
protected function attendeesAddedEvent(AttendeesAddedEvent $event): void {
foreach ($event->getAttendees() as $attendee) {
$this->logger->debug($attendee->getActorType() . ' "' . $attendee->getActorId() . '" added to room "' . $event->getRoom()->getToken() . '"', ['app' => 'spreed-bfp']);
if ($attendee->getActorType() === Attendee::ACTOR_GROUPS) {
$this->sendSystemMessage($event->getRoom(), 'group_added', ['group' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_CIRCLES) {
$this->sendSystemMessage($event->getRoom(), 'circle_added', ['circle' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_FEDERATED_USERS) {
$this->sendSystemMessage($event->getRoom(), 'federated_user_added', ['federated_user' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_PHONES) {
$this->sendSystemMessage($event->getRoom(), 'phone_added', ['phone' => $attendee->getActorId(), 'name' => $attendee->getDisplayName()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_USERS) {
$this->addSystemMessageUserAdded($event, $attendee);
}
}
}
protected function attendeesRemovedEvent(AttendeesRemovedEvent $event): void {
foreach ($event->getAttendees() as $attendee) {
$this->logger->debug($attendee->getActorType() . ' "' . $attendee->getActorId() . '" removed from room "' . $event->getRoom()->getToken() . '"', ['app' => 'spreed-bfp']);
if ($attendee->getActorType() === Attendee::ACTOR_GROUPS) {
$this->sendSystemMessage($event->getRoom(), 'group_removed', ['group' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_CIRCLES) {
$this->sendSystemMessage($event->getRoom(), 'circle_removed', ['circle' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_FEDERATED_USERS) {
$this->sendSystemMessage($event->getRoom(), 'federated_user_removed', ['federated_user' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_PHONES) {
$this->sendSystemMessage($event->getRoom(), 'phone_removed', ['phone' => $attendee->getActorId(), 'name' => $attendee->getDisplayName()]);
}
}
}
protected function sendSystemMessage(
Room $room,
string $message,
array $parameters = [],
?Participant $participant = null,
bool $shouldSkipLastMessageUpdate = false,
bool $silent = false,
bool $forceSystemAsActor = false,
?int $replyTo = null,
?IComment $parent = null,
?int $threadId = null,
): IComment {
if ($participant instanceof Participant) {
$actorType = $participant->getAttendee()->getActorType();
$actorId = $participant->getAttendee()->getActorId();
} elseif ($forceSystemAsActor) {
$actorType = Attendee::ACTOR_GUESTS;
$actorId = Attendee::ACTOR_ID_SYSTEM;
} else {
$user = $this->userSession->getUser();
if ($user instanceof IUser) {
$actorType = Attendee::ACTOR_USERS;
$actorId = $user->getUID();
} elseif (\OC::$CLI || $this->session->exists('talk-overwrite-actor-cli')) {
$actorType = Attendee::ACTOR_GUESTS;
$actorId = Attendee::ACTOR_ID_CLI;
} elseif ($this->session->exists('talk-overwrite-actor-type')) {
$actorType = $this->session->get('talk-overwrite-actor-type');
$actorId = $this->session->get('talk-overwrite-actor-id');
} elseif ($this->session->exists('talk-overwrite-actor-id')) {
$actorType = Attendee::ACTOR_USERS;
$actorId = $this->session->get('talk-overwrite-actor-id');
} else {
$actorType = Attendee::ACTOR_GUESTS;
$sessionId = $this->talkSession->getSessionForRoom($room->getToken());
$actorId = $sessionId ? sha1($sessionId) : 'failed-to-get-session';
}
}
// Little hack to get the reference id from the share request into
// the system message left for the share in the chat.
$referenceId = $this->request->getParam('referenceId', null);
if ($referenceId !== null) {
$referenceId = (string)$referenceId;
}
if ($parent === null && $replyTo !== null) {
try {
$parentComment = $this->chatManager->getParentComment($room, (string)$replyTo);
$parentMessage = $this->messageParser->createMessage($room, $participant, $parentComment, $this->l);
$this->messageParser->parseMessage($parentMessage, true);
if ($parentMessage->isReplyable()) {
$parent = $parentComment;
}
} catch (NotFoundException) {
}
} elseif ($parent === null && $threadId !== null) {
if (!$this->threadService->validateThread($room->getId(), $threadId)) {
$threadId = null;
}
}
return $this->chatManager->addSystemMessage(
$room, $participant, $actorType, $actorId,
json_encode(['message' => $message, 'parameters' => $parameters]),
$this->timeFactory->getDateTime(),
$message === 'file_shared',
$referenceId,
$parent,
$shouldSkipLastMessageUpdate,
$silent,
$threadId ?? 0,
);
}
protected function getUserId(): ?string {
$user = $this->userSession->getUser();
return $user instanceof IUser ? $user->getUID() : null;
}
protected function afterSetMessageExpiration(RoomModifiedEvent $event): void {
$seconds = $event->getNewValue();
if ($seconds > 0) {
$message = 'message_expiration_enabled';
} else {
$message = 'message_expiration_disabled';
}
$this->sendSystemMessage(
$event->getRoom(),
$message,
[
'seconds' => $seconds,
]
);
}
protected function setCallRecording(RoomModifiedEvent $event): void {
$recordingHasStarted = in_array($event->getOldValue(), [Room::RECORDING_NONE, Room::RECORDING_VIDEO_STARTING, Room::RECORDING_AUDIO_STARTING, Room::RECORDING_FAILED], true)
&& in_array($event->getNewValue(), [Room::RECORDING_VIDEO, Room::RECORDING_AUDIO], true);
$recordingHasStopped = in_array($event->getOldValue(), [Room::RECORDING_VIDEO, Room::RECORDING_AUDIO], true)
&& $event->getNewValue() === Room::RECORDING_NONE;
$recordingHasFailed = in_array($event->getOldValue(), [Room::RECORDING_VIDEO, Room::RECORDING_AUDIO], true)
&& $event->getNewValue() === Room::RECORDING_FAILED;
if (!$recordingHasStarted && !$recordingHasStopped && !$recordingHasFailed) {
return;
}
$actor = $event->getActor();
if ($recordingHasStopped && $actor === null) {
// No actor means the recording was stopped by the end of the call.
// So we are not generating a system message
return;
}
$prefix = $this->getCallRecordingPrefix($event);
$suffix = $this->getCallRecordingSuffix($event);
$systemMessage = $prefix . 'recording_' . $suffix;
$this->sendSystemMessage($event->getRoom(), $systemMessage, [], $actor);
}
protected function getCallRecordingSuffix(RoomModifiedEvent $event): string {
$newStatus = $event->getNewValue();
$startStatus = [
Room::RECORDING_VIDEO,
Room::RECORDING_AUDIO,
];
if (in_array($newStatus, $startStatus, true)) {
return 'started';
}
if ($newStatus === Room::RECORDING_FAILED) {
return 'failed';
}
return 'stopped';
}
protected function getCallRecordingPrefix(RoomModifiedEvent $event): string {
$newValue = $event->getNewValue();
$oldValue = $event->getOldValue();
$isAudioStatus = $newValue === Room::RECORDING_AUDIO
|| ($oldValue === Room::RECORDING_AUDIO && $newValue !== Room::RECORDING_FAILED);
return $isAudioStatus ? 'audio_' : '';
}
protected function avatarChanged(RoomModifiedEvent $event): void {
if ($event->getNewValue()) {
if ($this->isCreatingNoteToSelf($event) || $this->isCreatingSample($event)) {
return;
}
$message = 'avatar_set';
} else {
$message = 'avatar_removed';
}
$this->sendSystemMessage($event->getRoom(), $message);
}
protected function isCreatingNoteToSelf(RoomModifiedEvent $event): bool {
if ($event->getRoom()->getType() !== Room::TYPE_NOTE_TO_SELF) {
return false;
}
$exception = new \Exception();
$trace = $exception->getTrace();
foreach ($trace as $step) {
if (isset($step['class']) && $step['class'] === NoteToSelfService::class
&& isset($step['function']) && $step['function'] === 'initialCreateNoteToSelfForUser') {
return true;
}
if (isset($step['class']) && $step['class'] === NoteToSelfService::class
&& isset($step['function']) && $step['function'] === 'ensureNoteToSelfExistsForUser') {
return true;
}
}
return false;
}
protected function isCreatingSample(ARoomEvent $event): bool {
if ($event->getRoom()->getType() !== Room::TYPE_GROUP) {
return false;
}
$exception = new \Exception();
$trace = $exception->getTrace();
foreach ($trace as $step) {
if (isset($step['class']) && $step['class'] === SampleConversationsService::class
&& isset($step['function']) && $step['function'] === 'initialCreateSamples') {
return true;
}
}
return false;
}
protected function isCreatingNoteToSelfAutomatically(RoomCreatedEvent $event): bool {
if ($event->getRoom()->getType() !== Room::TYPE_NOTE_TO_SELF) {
return false;
}
$exception = new \Exception();
$trace = $exception->getTrace();
foreach ($trace as $step) {
if (isset($step['class']) && $step['class'] === NoteToSelfService::class
&& isset($step['function']) && $step['function'] === 'initialCreateNoteToSelfForUser') {
return true;
}
}
return false;
}
}