Skip to content

Commit

Permalink
Merge pull request #12959 from nextcloud/feat/12887/user-statuses-in-…
Browse files Browse the repository at this point in the history
…federated-conversations

feat(statuses): Post-load local user statuses in federated conversations
  • Loading branch information
nickvergessen authored Aug 15, 2024
2 parents d4899f7 + c485b74 commit fffe685
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 7 deletions.
40 changes: 38 additions & 2 deletions lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
}
Expand Down
2 changes: 0 additions & 2 deletions lib/Federation/Proxy/TalkV1/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public function __construct(
/**
* @see \OCA\Talk\Controller\RoomController::getParticipants()
*
* @param bool $includeStatus Include the user statuses
* @return DataResponse<Http::STATUS_OK, TalkParticipant[], array{X-Nextcloud-Has-User-Statuses?: bool}>
* @throws CannotReachRemoteException
*
Expand All @@ -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 = [];
Expand Down
14 changes: 11 additions & 3 deletions tests/integration/features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
40 changes: 40 additions & 0 deletions tests/integration/features/federation/user-statuses.feature
Original file line number Diff line number Diff line change
@@ -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 |

0 comments on commit fffe685

Please sign in to comment.