diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 5f7e0c97606..9a59da0bd95 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -861,7 +861,43 @@ public function getParticipants(bool $includeStatus = false): DataResponse { if ($this->room->isFederatedConversation()) { /** @var \OCA\Talk\Federation\Proxy\TalkV1\Controller\RoomController $proxy */ $proxy = \OCP\Server::get(\OCA\Talk\Federation\Proxy\TalkV1\Controller\RoomController::class); - return $proxy->getParticipants($this->room, $this->participant); + $response = $proxy->getParticipants($this->room, $this->participant); + $data = $response->getData(); + + if ($this->userId !== null + && $includeStatus + && count($data) < Config::USER_STATUS_INTEGRATION_LIMIT + && $this->appManager->isEnabledForUser('user_status')) { + $userIds = array_filter(array_map(static function (array $parsedParticipant): ?string { + if ($parsedParticipant['actorType'] === Attendee::ACTOR_USERS) { + return $parsedParticipant['actorId']; + } + return null; + }, $data)); + + $statuses = $this->statusManager->getUserStatuses($userIds); + $data = array_map(static function (array $parsedParticipant) use ($statuses): array { + if ($parsedParticipant['actorType'] === Attendee::ACTOR_USERS + && isset($statuses[$parsedParticipant['actorId']])) { + $userId = $parsedParticipant['actorId']; + if (isset($statuses[$userId])) { + $parsedParticipant['status'] = $statuses[$userId]->getStatus(); + $parsedParticipant['statusIcon'] = $statuses[$userId]->getIcon(); + $parsedParticipant['statusMessage'] = $statuses[$userId]->getMessage(); + $parsedParticipant['statusClearAt'] = $statuses[$userId]->getClearAt()?->getTimestamp(); + } else { + $parsedParticipant['status'] = IUserStatus::OFFLINE; + $parsedParticipant['statusIcon'] = null; + $parsedParticipant['statusMessage'] = null; + $parsedParticipant['statusClearAt'] = null; + } + } + return $parsedParticipant; + }, $data); + } + + $response->setData($data); + return $response; } if ($this->participant->getAttendee()->getParticipantType() === Participant::GUEST) { @@ -916,7 +952,7 @@ protected function formatParticipantList(array $participants, bool $includeStatu && $includeStatus && count($participants) < Config::USER_STATUS_INTEGRATION_LIMIT && $this->appManager->isEnabledForUser('user_status')) { - $userIds = array_filter(array_map(static function (Participant $participant) { + $userIds = array_filter(array_map(static function (Participant $participant): ?string { if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) { return $participant->getAttendee()->getActorId(); } diff --git a/lib/Federation/Proxy/TalkV1/Controller/RoomController.php b/lib/Federation/Proxy/TalkV1/Controller/RoomController.php index c79a2f4b6e8..963e3eb2da2 100644 --- a/lib/Federation/Proxy/TalkV1/Controller/RoomController.php +++ b/lib/Federation/Proxy/TalkV1/Controller/RoomController.php @@ -33,7 +33,6 @@ public function __construct( /** * @see \OCA\Talk\Controller\RoomController::getParticipants() * - * @param bool $includeStatus Include the user statuses * @return DataResponse * @throws CannotReachRemoteException * @@ -50,7 +49,6 @@ public function getParticipants(Room $room, Participant $participant): DataRespo /** @var TalkParticipant[] $data */ $data = $this->proxy->getOCSData($proxy); - // FIXME post-load status information of now local users /** @var TalkParticipant[] $data */ $data = $this->userConverter->convertAttendees($room, $data, 'actorType', 'actorId', 'displayName'); $headers = []; diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php index f62f4647035..c1a8e8ea916 100644 --- a/tests/integration/features/bootstrap/FeatureContext.php +++ b/tests/integration/features/bootstrap/FeatureContext.php @@ -738,17 +738,18 @@ public function userIsParticipantOfRoom(string $user, string $isOrNotParticipant } /** - * @Then /^user "([^"]*)" sees the following attendees in room "([^"]*)" with (\d+) \((v4)\)$/ + * @Then /^user "([^"]*)" sees the following attendees( with status)? in room "([^"]*)" with (\d+) \((v4)\)$/ * * @param string $user + * @param string $withStatus * @param string $identifier * @param int $statusCode * @param string $apiVersion * @param TableNode $formData */ - public function userSeesAttendeesInRoom(string $user, string $identifier, int $statusCode, string $apiVersion, ?TableNode $formData = null): void { + public function userSeesAttendeesInRoom(string $user, string $withStatus, string $identifier, int $statusCode, string $apiVersion, ?TableNode $formData = null): void { $this->setCurrentUser($user); - $this->sendRequest('GET', '/apps/spreed/api/' . $apiVersion . '/room/' . self::$identifierToToken[$identifier] . '/participants'); + $this->sendRequest('GET', '/apps/spreed/api/' . $apiVersion . '/room/' . self::$identifierToToken[$identifier] . '/participants?includeStatus=' . ($withStatus === ' with status' ? '1' : '0')); $this->assertStatusCode($this->response, $statusCode); if ($formData instanceof TableNode) { @@ -821,6 +822,9 @@ protected function assertAttendeeList(string $identifier, ?TableNode $formData, if (isset($expectedKeys['callId'])) { $data['callId'] = (string) $attendee['callId']; } + if (isset($expectedKeys['status'], $attendee['status'])) { + $data['status'] = (string) $attendee['status']; + } if (isset($expectedKeys['sessionIds'])) { $sessionIds = '['; foreach ($attendee['sessionIds'] as $sessionId) { @@ -898,6 +902,10 @@ protected function assertAttendeeList(string $identifier, ?TableNode $formData, if (isset($attendee['actorType']) && $attendee['actorType'] === 'phones') { $attendee['participantType'] = (string)$this->mapParticipantTypeTestInput($attendee['participantType']); } + + if (isset($attendee['status']) && $attendee['status'] === 'ABSENT') { + unset($attendee['status']); + } return $attendee; }, $formData->getHash(), $result); $expected = array_filter($expected); diff --git a/tests/integration/features/federation/user-statuses.feature b/tests/integration/features/federation/user-statuses.feature new file mode 100644 index 00000000000..dbe0cf69233 --- /dev/null +++ b/tests/integration/features/federation/user-statuses.feature @@ -0,0 +1,40 @@ +Feature: federation/user-statuses + + Background: + Given using server "REMOTE" + And user "participant2" exists + And user "participant3" exists + And the following "spreed" app config is set + | federation_enabled | yes | + And using server "LOCAL" + And user "participant1" exists + And the following "spreed" app config is set + | federation_enabled | yes | + + Scenario: User statuses are added to the participant request in federated conversations + Given user "participant1" creates room "room" (v4) + | roomType | 2 | + | roomName | room | + And user "participant1" adds federated_user "participant2@REMOTE" to room "room" with 200 (v4) + And user "participant1" adds federated_user "participant3@REMOTE" to room "room" with 200 (v4) + And using server "REMOTE" + And user "participant2" has the following invitations (v1) + | remoteServerUrl | remoteToken | state | inviterCloudId | inviterDisplayName | + | LOCAL | room | 0 | participant1@http://localhost:8080 | participant1-displayname | + And user "participant2" accepts invite to room "room" of server "LOCAL" with 200 (v1) + | id | name | type | remoteServer | remoteToken | + | LOCAL::room | room | 2 | LOCAL | room | + Then user "participant2" set status to "away" with 200 (v1) + And user "participant3" has the following invitations (v1) + | remoteServerUrl | remoteToken | state | inviterCloudId | inviterDisplayName | + | LOCAL | room | 0 | participant1@http://localhost:8080 | participant1-displayname | + And user "participant3" accepts invite to room "room" of server "LOCAL" with 200 (v1) + | id | name | type | remoteServer | remoteToken | + | LOCAL::room | room | 2 | LOCAL | room | + Then user "participant3" set status to "dnd" with 200 (v1) + And user "participant2" is participant of room "LOCAL::room" (v4) + And user "participant2" sees the following attendees with status in room "LOCAL::room" with 200 (v4) + | actorType | actorId | participantType | status | + | federated_users | participant1@{$LOCAL_URL} | 1 | ABSENT | + | users | participant2 | 3 | away | + | users | participant3 | 3 | dnd |