diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php index a4c349cbc1ba..fc145c8858d7 100644 --- a/lib/Chat/ChatManager.php +++ b/lib/Chat/ChatManager.php @@ -177,17 +177,20 @@ public function addSystemMessage( if ($sendNotifications) { /** @var ?IComment $captionComment */ $captionComment = null; - $alreadyNotifiedUsers = $usersDirectlyMentioned = []; + $alreadyNotifiedUsers = $usersDirectlyMentioned = $federatedUsersDirectlyMentioned = []; if ($messageType === 'file_shared') { if (isset($messageDecoded['parameters']['metaData']['caption'])) { $captionComment = clone $comment; $captionComment->setMessage($messageDecoded['parameters']['metaData']['caption'], self::MAX_CHAT_LENGTH); $usersDirectlyMentioned = $this->notifier->getMentionedUserIds($captionComment); + $federatedUsersDirectlyMentioned = $this->notifier->getMentionedCloudIds($captionComment); } if ($replyTo instanceof IComment) { $alreadyNotifiedUsers = $this->notifier->notifyReplyToAuthor($chat, $comment, $replyTo, $silent); if ($replyTo->getActorType() === Attendee::ACTOR_USERS) { $usersDirectlyMentioned[] = $replyTo->getActorId(); + } elseif ($replyTo->getActorType() === Attendee::ACTOR_FEDERATED_USERS) { + $federatedUsersDirectlyMentioned[] = $replyTo->getActorId(); } } } @@ -195,7 +198,10 @@ public function addSystemMessage( $alreadyNotifiedUsers = $this->notifier->notifyMentionedUsers($chat, $captionComment ?? $comment, $alreadyNotifiedUsers, $silent); if (!empty($alreadyNotifiedUsers)) { $userIds = array_column($alreadyNotifiedUsers, 'id'); - $this->participantService->markUsersAsMentioned($chat, $userIds, (int) $comment->getId(), $usersDirectlyMentioned); + $this->participantService->markUsersAsMentioned($chat, Attendee::ACTOR_USERS, $userIds, (int) $comment->getId(), $usersDirectlyMentioned); + } + if (!empty($federatedUsersDirectlyMentioned)) { + $this->participantService->markUsersAsMentioned($chat, Attendee::ACTOR_FEDERATED_USERS, $federatedUsersDirectlyMentioned, (int) $comment->getId(), $federatedUsersDirectlyMentioned); } $this->notifier->notifyOtherParticipant($chat, $comment, [], $silent); @@ -326,17 +332,23 @@ public function sendMessage(Room $chat, ?Participant $participant, string $actor $alreadyNotifiedUsers = []; $usersDirectlyMentioned = $this->notifier->getMentionedUserIds($comment); + $federatedUsersDirectlyMentioned = $this->notifier->getMentionedCloudIds($comment); if ($replyTo instanceof IComment) { $alreadyNotifiedUsers = $this->notifier->notifyReplyToAuthor($chat, $comment, $replyTo, $silent); if ($replyTo->getActorType() === Attendee::ACTOR_USERS) { $usersDirectlyMentioned[] = $replyTo->getActorId(); + } elseif ($replyTo->getActorType() === Attendee::ACTOR_FEDERATED_USERS) { + $federatedUsersDirectlyMentioned[] = $replyTo->getActorId(); } } $alreadyNotifiedUsers = $this->notifier->notifyMentionedUsers($chat, $comment, $alreadyNotifiedUsers, $silent); if (!empty($alreadyNotifiedUsers)) { $userIds = array_column($alreadyNotifiedUsers, 'id'); - $this->participantService->markUsersAsMentioned($chat, $userIds, (int) $comment->getId(), $usersDirectlyMentioned); + $this->participantService->markUsersAsMentioned($chat, Attendee::ACTOR_USERS, $userIds, (int) $comment->getId(), $usersDirectlyMentioned); + } + if (!empty($federatedUsersDirectlyMentioned)) { + $this->participantService->markUsersAsMentioned($chat, Attendee::ACTOR_FEDERATED_USERS, $federatedUsersDirectlyMentioned, (int) $comment->getId(), $federatedUsersDirectlyMentioned); } // User was not mentioned, send a normal notification @@ -561,12 +573,16 @@ public function editMessage(Room $chat, IComment $comment, Participant $particip if (!empty($addedMentions)) { $usersDirectlyMentionedAfter = $this->notifier->getMentionedUserIds($comment); + $federatedUsersDirectlyMentionedAfter = $this->notifier->getMentionedCloudIds($comment); $addedUsersDirectMentioned = array_diff($usersDirectlyMentionedAfter, $usersDirectlyMentionedBefore); $alreadyNotifiedUsers = $this->notifier->notifyMentionedUsers($chat, $comment, $usersToNotifyBefore, silent: false); if (!empty($alreadyNotifiedUsers)) { $userIds = array_column($alreadyNotifiedUsers, 'id'); - $this->participantService->markUsersAsMentioned($chat, $userIds, (int) $comment->getId(), $addedUsersDirectMentioned); + $this->participantService->markUsersAsMentioned($chat, Attendee::ACTOR_USERS, $userIds, (int) $comment->getId(), $addedUsersDirectMentioned); + } + if (!empty($federatedUsersDirectlyMentionedAfter)) { + $this->participantService->markUsersAsMentioned($chat, Attendee::ACTOR_FEDERATED_USERS, $federatedUsersDirectlyMentionedAfter, (int) $comment->getId(), $federatedUsersDirectlyMentionedAfter); } } } diff --git a/lib/Chat/Notifier.php b/lib/Chat/Notifier.php index 8ba24bd1547c..7d6393dda466 100644 --- a/lib/Chat/Notifier.php +++ b/lib/Chat/Notifier.php @@ -202,11 +202,21 @@ private function addMentionAllToList(Room $chat, array $list): array { * @psalm-return array */ public function notifyReplyToAuthor(Room $chat, IComment $comment, IComment $replyTo, bool $silent): array { - if ($replyTo->getActorType() !== Attendee::ACTOR_USERS) { - // No reply notification when the replyTo-author was not a user + if ($replyTo->getActorType() !== Attendee::ACTOR_USERS && $replyTo->getActorType() !== Attendee::ACTOR_FEDERATED_USERS) { + // No reply notification when the replyTo-author was not a user or federated user return []; } + if ($replyTo->getActorType() === Attendee::ACTOR_FEDERATED_USERS) { + return [ + [ + 'id' => $replyTo->getActorId(), + 'type' => $replyTo->getActorType(), + 'reason' => 'reply', + ], + ]; + } + if (!$this->shouldMentionedUserBeNotified($replyTo->getActorId(), $comment, $chat)) { return []; } @@ -407,6 +417,19 @@ public function getMentionedUserIds(IComment $comment): array { }, $mentionedUsers); } + /** + * Returns the cloud IDs of the federated users mentioned in the given comment. + * + * @param IComment $comment + * @return string[] the mentioned cloud IDs + */ + public function getMentionedCloudIds(IComment $comment): array { + $mentionedFederatedUsers = $this->getMentionedFederatedUsers($comment); + return array_map(static function ($mentionedUser) { + return $mentionedUser['id']; + }, $mentionedFederatedUsers); + } + /** * @param IComment $comment * @return array[] @@ -427,7 +450,34 @@ private function getMentionedUsers(IComment $comment): array { $mentionedUsers[] = [ 'id' => $mention['id'], - 'type' => 'users', + 'type' => Attendee::ACTOR_USERS, + 'reason' => 'direct', + ]; + } + return $mentionedUsers; + } + + /** + * @param IComment $comment + * @return array[] + * @psalm-return array + */ + private function getMentionedFederatedUsers(IComment $comment): array { + $mentions = $comment->getMentions(); + + if (empty($mentions)) { + return []; + } + + $mentionedUsers = []; + foreach ($mentions as $mention) { + if ($mention['type'] !== 'federated_user') { + continue; + } + + $mentionedUsers[] = [ + 'id' => $mention['id'], + 'type' => Attendee::ACTOR_FEDERATED_USERS, 'reason' => 'direct', ]; } diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 6d0711ed6c31..7ea81e69c7e0 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -1283,28 +1283,26 @@ public function updateCallFlags(Room $room, Participant $participant, int $flags } /** - * @param Room $room - * @param string[] $userIds - * @param int $messageId + * @param string[] $actorIds * @param string[] $usersDirectlyMentioned */ - public function markUsersAsMentioned(Room $room, array $userIds, int $messageId, array $usersDirectlyMentioned): void { + public function markUsersAsMentioned(Room $room, string $actorType, array $actorIds, int $messageId, array $actorsDirectlyMentioned): void { $update = $this->connection->getQueryBuilder(); $update->update('talk_attendees') ->set('last_mention_message', $update->createNamedParameter($messageId, IQueryBuilder::PARAM_INT)) ->where($update->expr()->eq('room_id', $update->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))) - ->andWhere($update->expr()->eq('actor_type', $update->createNamedParameter(Attendee::ACTOR_USERS))) - ->andWhere($update->expr()->in('actor_id', $update->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY))) + ->andWhere($update->expr()->eq('actor_type', $update->createNamedParameter($actorType))) + ->andWhere($update->expr()->in('actor_id', $update->createNamedParameter($actorIds, IQueryBuilder::PARAM_STR_ARRAY))) ->andWhere($update->expr()->lt('last_mention_message', $update->createNamedParameter($messageId, IQueryBuilder::PARAM_INT))); $update->executeStatement(); - if (!empty($usersDirectlyMentioned)) { + if (!empty($actorsDirectlyMentioned)) { $update = $this->connection->getQueryBuilder(); $update->update('talk_attendees') ->set('last_mention_direct', $update->createNamedParameter($messageId, IQueryBuilder::PARAM_INT)) ->where($update->expr()->eq('room_id', $update->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))) - ->andWhere($update->expr()->eq('actor_type', $update->createNamedParameter(Attendee::ACTOR_USERS))) - ->andWhere($update->expr()->in('actor_id', $update->createNamedParameter($usersDirectlyMentioned, IQueryBuilder::PARAM_STR_ARRAY))) + ->andWhere($update->expr()->eq('actor_type', $update->createNamedParameter($actorType))) + ->andWhere($update->expr()->in('actor_id', $update->createNamedParameter($actorsDirectlyMentioned, IQueryBuilder::PARAM_STR_ARRAY))) ->andWhere($update->expr()->lt('last_mention_direct', $update->createNamedParameter($messageId, IQueryBuilder::PARAM_INT))); $update->executeStatement(); }