Skip to content

Commit

Permalink
feat(federation): Federate unread information to proxies
Browse files Browse the repository at this point in the history
Signed-off-by: Joas Schilling <coding@schilljs.com>
  • Loading branch information
nickvergessen committed Feb 28, 2024
1 parent 6678d24 commit 4219603
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 9 deletions.
6 changes: 6 additions & 0 deletions lib/Federation/BackendNotifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ public function sendRoomModifiedUpdate(
/**
* Send information to remote participants that a message was posted
* Sent from Host server to Remote participant server
*
* @param array{unreadMessages: int, unreadMention: bool, unreadMentionDirect: bool} $unreadInfo
*/
public function sendMessageUpdate(
string $remoteServer,
Expand All @@ -286,6 +288,7 @@ public function sendMessageUpdate(
string $accessToken,
string $localToken,
array $messageData,
array $unreadInfo,
): void {
$remote = $this->prepareRemoteUrl($remoteServer);

Expand All @@ -299,6 +302,7 @@ public function sendMessageUpdate(
'sharedSecret' => $accessToken,
'remoteToken' => $localToken,
'messageData' => $messageData,
'unreadInfo' => $unreadInfo,
],
);

Expand All @@ -324,6 +328,8 @@ public function sendUpdateDataToRemote(string $remote, array $data, int $try): v
}

protected function sendUpdateToRemote(string $remote, ICloudFederationNotification $notification, int $try = 0): void {
\OC::$server->getLogger()->error('sendUpdateToRemote');
\OC::$server->getLogger()->error(json_encode($notification->getMessage()));
$response = $this->federationProviderManager->sendNotification($remote, $notification);
if (!is_array($response)) {
$this->jobList->add(RetryJob::class,
Expand Down
20 changes: 18 additions & 2 deletions lib/Federation/CloudFederationProviderTalk.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use OCA\Talk\Events\AAttendeeRemovedEvent;
use OCA\Talk\Events\ARoomModifiedEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Model\Attendee;
Expand Down Expand Up @@ -309,7 +310,7 @@ private function roomModified(int $remoteAttendeeId, array $notification): array

/**
* @param int $remoteAttendeeId
* @param array{remoteServerUrl: string, sharedSecret: string, remoteToken: string, messageData: array{remoteMessageId: int, actorType: string, actorId: string, actorDisplayName: string, messageType: string, systemMessage: string, expirationDatetime: string, message: string, messageParameter: string}} $notification
* @param array{remoteServerUrl: string, sharedSecret: string, remoteToken: string, messageData: array{remoteMessageId: int, actorType: string, actorId: string, actorDisplayName: string, messageType: string, systemMessage: string, expirationDatetime: string, message: string, messageParameter: string}, unreadInfo: array{unreadMessages: int, unreadMention: bool, unreadMentionDirect: bool}} $notification
* @return array
* @throws ActionNotSupportedException
* @throws AuthenticationFailedException
Expand Down Expand Up @@ -338,7 +339,9 @@ private function messagePosted(int $remoteAttendeeId, array $notification): arra
$message->setActorDisplayName($notification['messageData']['actorDisplayName']);
$message->setMessageType($notification['messageData']['messageType']);
$message->setSystemMessage($notification['messageData']['systemMessage']);
$message->setExpirationDateTime(new \DateTimeImmutable($notification['messageData']['expirationDatetime']));
if ($notification['messageData']['expirationDatetime']) {
$message->setExpirationDateTime(new \DateTimeImmutable($notification['messageData']['expirationDatetime']));
}
$message->setMessage($notification['messageData']['message']);
$message->setMessageParameters($notification['messageData']['messageParameter']);
$this->proxyCacheMessagesMapper->insert($message);
Expand All @@ -351,6 +354,19 @@ private function messagePosted(int $remoteAttendeeId, array $notification): arra
}
}

try {
$participant = $this->participantService->getParticipant($room, $invite->getUserId(), false);
} catch (ParticipantNotFoundException) {
throw new ShareNotFound();
}

$this->participantService->updateUnreadInfoForProxyParticipant(
$participant,
$notification['unreadInfo']['unreadMessages'],
$notification['unreadInfo']['unreadMention'],
$notification['unreadInfo']['unreadMentionDirect'],
);

return [];
}

Expand Down
19 changes: 13 additions & 6 deletions lib/Federation/Proxy/TalkV1/Notifier/MessageSentListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public function __construct(
protected ICloudIdManager $cloudIdManager,
protected MessageParser $messageParser,
protected IFactory $l10nFactory,
protected ChatManager $chatManager,
) {
}

Expand Down Expand Up @@ -90,22 +91,28 @@ public function handle(Event $event): void {
'messageParameter' => json_encode($chatMessage->getMessageParameters()),
];

$notifiedServers = [];
$participants = $this->participantService->getParticipantsByActorType($event->getRoom(), Attendee::ACTOR_FEDERATED_USERS);
foreach ($participants as $participant) {
$cloudId = $this->cloudIdManager->resolveCloudId($participant->getAttendee()->getActorId());
$attendee = $participant->getAttendee();
$cloudId = $this->cloudIdManager->resolveCloudId($attendee->getActorId());

if (isset($notifiedServers[$cloudId->getRemote()])) {
continue;
}
$notifiedServers[$cloudId->getRemote()] = true;
$lastReadMessage = $attendee->getLastReadMessage();
$lastMention = $attendee->getLastMentionMessage();
$lastMentionDirect = $attendee->getLastMentionDirect();

$unreadInfo = [
'unreadMessages' => $this->chatManager->getUnreadCount($event->getRoom(), $lastReadMessage),
'unreadMention' => $lastMention !== 0 && $lastReadMessage < $lastMention,
'unreadMentionDirect' => $lastMentionDirect !== 0 && $lastReadMessage < $lastMentionDirect
];

$this->backendNotifier->sendMessageUpdate(
$cloudId->getRemote(),
$participant->getAttendee()->getId(),
$participant->getAttendee()->getAccessToken(),
$event->getRoom()->getToken(),
$messageData,
$unreadInfo,
);
}
}
Expand Down
8 changes: 8 additions & 0 deletions lib/Service/ParticipantService.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,14 @@ public function updateLastReadMessage(Participant $participant, int $lastReadMes
$this->attendeeMapper->update($attendee);
}

public function updateUnreadInfoForProxyParticipant(Participant $participant, int $unreadMessageCount, bool $hasMention, bool $hadDirectMention): void {
$attendee = $participant->getAttendee();
$attendee->setLastReadMessage($unreadMessageCount);
$attendee->setLastMentionMessage($hasMention ? 1 : 0);
$attendee->setLastMentionDirect($hadDirectMention ? 1 : 0);
$this->attendeeMapper->update($attendee);
}

public function updateFavoriteStatus(Participant $participant, bool $isFavorite): void {
$attendee = $participant->getAttendee();
$attendee->setFavorite($isFavorite);
Expand Down
8 changes: 7 additions & 1 deletion lib/Service/RoomFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,13 @@ public function formatRoomV4(

if ($attendee->getActorType() === Attendee::ACTOR_USERS) {
$currentUser = $this->userManager->get($attendee->getActorId());
if ($currentUser instanceof IUser) {
if ($room->getRemoteServer() !== '') {
// For proxy conversations the information is the real counter,
// not the message ID requiring math afterward.
$roomData['unreadMessages'] = $attendee->getLastReadMessage();
$roomData['unreadMention'] = (bool) $attendee->getLastMentionMessage();
$roomData['unreadMentionDirect'] = (bool) $attendee->getLastMentionDirect();
} elseif ($currentUser instanceof IUser) {
$lastReadMessage = $attendee->getLastReadMessage();
if ($lastReadMessage === -1) {
/*
Expand Down

0 comments on commit 4219603

Please sign in to comment.