Browse Source

feat: Propagate "in call" status of rooms to federated servers

"In call" status is set from two different properties, "active since"
and "call flag". Call flags can be modified independently, but "active
since" is always linked to setting call flags, so the event needs to
include both properties.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
pull/12668/head
Daniel Calviño Sánchez 1 year ago
parent
commit
5162e9469b
  1. 6
      docs/events.md
  2. 2
      lib/AppInfo/Application.php
  3. 36
      lib/Events/AActiveSinceModifiedEvent.php
  4. 9
      lib/Events/ARoomModifiedEvent.php
  5. 12
      lib/Events/ActiveSinceModifiedEvent.php
  6. 12
      lib/Events/BeforeActiveSinceModifiedEvent.php
  7. 43
      lib/Federation/BackendNotifier.php
  8. 13
      lib/Federation/CloudFederationProviderTalk.php
  9. 24
      lib/Federation/Proxy/TalkV1/Notifier/RoomModifiedListener.php
  10. 41
      lib/Service/RoomService.php

6
docs/events.md

@ -47,6 +47,12 @@ Allows to verify a password and set a redirect URL for the invalid case
* Event: `OCA\Talk\Events\RoomPasswordVerifyEvent`
* Since: 18.0.0
### Active since modified
* Before event: `OCA\Talk\Events\BeforeActiveSinceModifiedEvent`
* After event: `OCA\Talk\Events\ActiveSinceModifiedEvent`
* Since: 20.0.0
## Participant related events
### Attendees added

2
lib/AppInfo/Application.php

@ -30,6 +30,7 @@ use OCA\Talk\Collaboration\Resources\Listener as ResourceListener;
use OCA\Talk\Config;
use OCA\Talk\Dashboard\TalkWidget;
use OCA\Talk\Deck\DeckPluginLoader;
use OCA\Talk\Events\ActiveSinceModifiedEvent;
use OCA\Talk\Events\AttendeeRemovedEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Events\AttendeesRemovedEvent;
@ -263,6 +264,7 @@ class Application extends App implements IBootstrap {
// Federation listeners
$context->registerEventListener(BeforeRoomDeletedEvent::class, TalkV1BeforeRoomDeletedListener::class);
$context->registerEventListener(ActiveSinceModifiedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(LobbyModifiedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(RoomModifiedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(ChatMessageSentEvent::class, TalkV1MessageSentListener::class);

36
lib/Events/AActiveSinceModifiedEvent.php

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Talk\Events;
use OCA\Talk\Room;
abstract class AActiveSinceModifiedEvent extends ARoomModifiedEvent {
public function __construct(
Room $room,
?\DateTime $newValue,
?\DateTime $oldValue,
protected int $callFlag,
protected int $oldCallFlag,
) {
parent::__construct(
$room,
self::PROPERTY_ACTIVE_SINCE,
$newValue,
$oldValue,
);
}
public function getCallFlag(): int {
return $this->callFlag;
}
public function getOldCallFlag(): int {
return $this->oldCallFlag;
}
}

9
lib/Events/ARoomModifiedEvent.php

@ -12,6 +12,7 @@ use OCA\Talk\Participant;
use OCA\Talk\Room;
abstract class ARoomModifiedEvent extends ARoomEvent {
public const PROPERTY_ACTIVE_SINCE = 'activeSince';
public const PROPERTY_AVATAR = 'avatar';
public const PROPERTY_BREAKOUT_ROOM_MODE = 'breakoutRoomMode';
public const PROPERTY_BREAKOUT_ROOM_STATUS = 'breakoutRoomStatus';
@ -37,8 +38,8 @@ abstract class ARoomModifiedEvent extends ARoomEvent {
public function __construct(
Room $room,
protected string $property,
protected string|int $newValue,
protected string|int|null $oldValue = null,
protected \DateTime|string|int|null $newValue,
protected \DateTime|string|int|null $oldValue = null,
protected ?Participant $actor = null,
) {
parent::__construct($room);
@ -48,11 +49,11 @@ abstract class ARoomModifiedEvent extends ARoomEvent {
return $this->property;
}
public function getNewValue(): string|int {
public function getNewValue(): \DateTime|string|int|null {
return $this->newValue;
}
public function getOldValue(): string|int|null {
public function getOldValue(): \DateTime|string|int|null {
return $this->oldValue;
}

12
lib/Events/ActiveSinceModifiedEvent.php

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Talk\Events;
class ActiveSinceModifiedEvent extends AActiveSinceModifiedEvent {
}

12
lib/Events/BeforeActiveSinceModifiedEvent.php

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Talk\Events;
class BeforeActiveSinceModifiedEvent extends AActiveSinceModifiedEvent {
}

43
lib/Federation/BackendNotifier.php

@ -240,6 +240,49 @@ class BackendNotifier {
return $this->sendUpdateToRemote($remote, $notification);
}
/**
* Send information to remote participants that "active since" was updated
* Sent from Host server to Remote participant server
*/
public function sendRoomModifiedActiveSinceUpdate(
string $remoteServer,
int $localAttendeeId,
#[SensitiveParameter]
string $accessToken,
string $localToken,
string $changedProperty,
?\DateTime $newValue,
?\DateTime $oldValue,
int $callFlag,
): ?bool {
$remote = $this->prepareRemoteUrl($remoteServer);
if ($newValue instanceof \DateTime) {
$newValue = (string) $newValue->getTimestamp();
}
if ($oldValue instanceof \DateTime) {
$oldValue = (string) $oldValue->getTimestamp();
}
$notification = $this->cloudFederationFactory->getCloudFederationNotification();
$notification->setMessage(
FederationManager::NOTIFICATION_ROOM_MODIFIED,
FederationManager::TALK_ROOM_RESOURCE,
(string) $localAttendeeId,
[
'remoteServerUrl' => $this->getServerRemoteUrl(),
'sharedSecret' => $accessToken,
'remoteToken' => $localToken,
'changedProperty' => $changedProperty,
'newValue' => $newValue,
'oldValue' => $oldValue,
'callFlag' => $callFlag,
],
);
return $this->sendUpdateToRemote($remote, $notification);
}
/**
* Send information to remote participants that the lobby was updated
* Sent from Host server to Remote participant server

13
lib/Federation/CloudFederationProviderTalk.php

@ -288,7 +288,7 @@ class CloudFederationProviderTalk implements ICloudFederationProvider {
/**
* @param int $remoteAttendeeId
* @param array{remoteServerUrl: string, sharedSecret: string, remoteToken: string, changedProperty: string, newValue: string|int|bool|null, oldValue: string|int|bool|null, dateTime?: string, timerReached?: bool} $notification
* @param array{remoteServerUrl: string, sharedSecret: string, remoteToken: string, changedProperty: string, newValue: string|int|bool|null, oldValue: string|int|bool|null, callFlag?: int, dateTime?: string, timerReached?: bool} $notification
* @return array
* @throws ActionNotSupportedException
* @throws AuthenticationFailedException
@ -307,10 +307,19 @@ class CloudFederationProviderTalk implements ICloudFederationProvider {
throw new ShareNotFound(FederationManager::OCM_RESOURCE_NOT_FOUND);
}
if ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_AVATAR) {
if ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_ACTIVE_SINCE) {
if ($notification['newValue'] === null) {
$this->roomService->resetActiveSince($room);
} else {
$activeSince = \DateTime::createFromFormat('U', $notification['newValue']);
$this->roomService->setActiveSince($room, $activeSince, $notification['callFlag']);
}
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_AVATAR) {
$this->roomService->setAvatar($room, $notification['newValue']);
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_DESCRIPTION) {
$this->roomService->setDescription($room, $notification['newValue']);
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_IN_CALL) {
$this->roomService->setActiveSince($room, $room->getActiveSince(), $notification['newValue']);
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_LOBBY) {
$dateTime = !empty($notification['dateTime']) ? \DateTime::createFromFormat('U', $notification['dateTime']) : null;
$this->roomService->setLobby($room, $notification['newValue'], $dateTime, $notification['timerReached'] ?? false);

24
lib/Federation/Proxy/TalkV1/Notifier/RoomModifiedListener.php

@ -8,7 +8,9 @@ declare(strict_types=1);
namespace OCA\Talk\Federation\Proxy\TalkV1\Notifier;
use OCA\Talk\Events\AActiveSinceModifiedEvent;
use OCA\Talk\Events\AAttendeeRemovedEvent;
use OCA\Talk\Events\ActiveSinceModifiedEvent;
use OCA\Talk\Events\ALobbyModifiedEvent;
use OCA\Talk\Events\ARoomModifiedEvent;
use OCA\Talk\Events\LobbyModifiedEvent;
@ -34,14 +36,17 @@ class RoomModifiedListener implements IEventListener {
}
public function handle(Event $event): void {
if (!$event instanceof LobbyModifiedEvent
if (!$event instanceof ActiveSinceModifiedEvent
&& !$event instanceof LobbyModifiedEvent
&& !$event instanceof RoomModifiedEvent) {
return;
}
if (!in_array($event->getProperty(), [
ARoomModifiedEvent::PROPERTY_ACTIVE_SINCE,
ARoomModifiedEvent::PROPERTY_AVATAR,
ARoomModifiedEvent::PROPERTY_DESCRIPTION,
ARoomModifiedEvent::PROPERTY_IN_CALL,
ARoomModifiedEvent::PROPERTY_LOBBY,
ARoomModifiedEvent::PROPERTY_NAME,
ARoomModifiedEvent::PROPERTY_READ_ONLY,
@ -54,7 +59,9 @@ class RoomModifiedListener implements IEventListener {
foreach ($participants as $participant) {
$cloudId = $this->cloudIdManager->resolveCloudId($participant->getAttendee()->getActorId());
if ($event instanceof ALobbyModifiedEvent) {
if ($event instanceof AActiveSinceModifiedEvent) {
$success = $this->notifyActiveSinceModified($cloudId, $participant, $event);
} elseif ($event instanceof ALobbyModifiedEvent) {
$success = $this->notifyLobbyModified($cloudId, $participant, $event);
} else {
$success = $this->notifyRoomModified($cloudId, $participant, $event);
@ -66,6 +73,19 @@ class RoomModifiedListener implements IEventListener {
}
}
private function notifyActiveSinceModified(ICloudId $cloudId, Participant $participant, AActiveSinceModifiedEvent $event) {
return $this->backendNotifier->sendRoomModifiedActiveSinceUpdate(
$cloudId->getRemote(),
$participant->getAttendee()->getId(),
$participant->getAttendee()->getAccessToken(),
$event->getRoom()->getToken(),
$event->getProperty(),
$event->getNewValue(),
$event->getOldValue(),
$event->getCallFlag(),
);
}
private function notifyLobbyModified(ICloudId $cloudId, Participant $participant, ALobbyModifiedEvent $event) {
return $this->backendNotifier->sendRoomModifiedLobbyUpdate(
$cloudId->getRemote(),

41
lib/Service/RoomService.php

@ -10,7 +10,9 @@ namespace OCA\Talk\Service;
use InvalidArgumentException;
use OCA\Talk\Config;
use OCA\Talk\Events\ActiveSinceModifiedEvent;
use OCA\Talk\Events\ARoomModifiedEvent;
use OCA\Talk\Events\BeforeActiveSinceModifiedEvent;
use OCA\Talk\Events\BeforeLobbyModifiedEvent;
use OCA\Talk\Events\BeforeRoomDeletedEvent;
use OCA\Talk\Events\BeforeRoomModifiedEvent;
@ -832,6 +834,16 @@ class RoomService {
}
public function resetActiveSince(Room $room): bool {
$oldActiveSince = $room->getActiveSince();
$oldCallFlag = $room->getCallFlag();
if ($oldActiveSince === null && $oldCallFlag === Participant::FLAG_DISCONNECTED) {
return false;
}
$event = new BeforeActiveSinceModifiedEvent($room, null, $oldActiveSince, Participant::FLAG_DISCONNECTED, $oldCallFlag);
$this->dispatcher->dispatchTyped($event);
$update = $this->db->getQueryBuilder();
$update->update('talk_rooms')
->set('active_since', $update->createNamedParameter(null, IQueryBuilder::PARAM_DATE))
@ -842,10 +854,30 @@ class RoomService {
$room->resetActiveSince();
return (bool) $update->executeStatement();
$result = (bool) $update->executeStatement();
$event = new ActiveSinceModifiedEvent($room, null, $oldActiveSince, Participant::FLAG_DISCONNECTED, $oldCallFlag);
$this->dispatcher->dispatchTyped($event);
return $result;
}
public function setActiveSince(Room $room, \DateTime $since, int $callFlag): bool {
$oldActiveSince = $room->getActiveSince();
$oldCallFlag = $room->getCallFlag();
if ($room->getActiveSince() instanceof \DateTime && $oldCallFlag === $callFlag) {
return false;
}
if ($room->getActiveSince() instanceof \DateTime) {
$event = new BeforeRoomModifiedEvent($room, ARoomModifiedEvent::PROPERTY_IN_CALL, $callFlag, $oldCallFlag);
$this->dispatcher->dispatchTyped($event);
} else {
$event = new BeforeActiveSinceModifiedEvent($room, $since, $oldActiveSince, $callFlag, $oldCallFlag);
$this->dispatcher->dispatchTyped($event);
}
$update = $this->db->getQueryBuilder();
$update->update('talk_rooms')
->set(
@ -857,6 +889,10 @@ class RoomService {
if ($room->getActiveSince() instanceof \DateTime) {
$room->setActiveSince($room->getActiveSince(), $callFlag);
$event = new RoomModifiedEvent($room, ARoomModifiedEvent::PROPERTY_IN_CALL, $callFlag, $oldCallFlag);
$this->dispatcher->dispatchTyped($event);
return false;
}
@ -869,6 +905,9 @@ class RoomService {
$room->setActiveSince($since, $callFlag);
$event = new ActiveSinceModifiedEvent($room, $since, $oldActiveSince, $callFlag, $oldCallFlag);
$this->dispatcher->dispatchTyped($event);
return true;
}

Loading…
Cancel
Save