diff --git a/docs/events.md b/docs/events.md index 93d902c6e1..89040ac151 100644 --- a/docs/events.md +++ b/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 diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index d53c36e611..444b064080 100644 --- a/lib/AppInfo/Application.php +++ b/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); diff --git a/lib/Events/AActiveSinceModifiedEvent.php b/lib/Events/AActiveSinceModifiedEvent.php new file mode 100644 index 0000000000..29083be46b --- /dev/null +++ b/lib/Events/AActiveSinceModifiedEvent.php @@ -0,0 +1,36 @@ +callFlag; + } + + public function getOldCallFlag(): int { + return $this->oldCallFlag; + } +} diff --git a/lib/Events/ARoomModifiedEvent.php b/lib/Events/ARoomModifiedEvent.php index d1e92dc723..4488e6e868 100644 --- a/lib/Events/ARoomModifiedEvent.php +++ b/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; } diff --git a/lib/Events/ActiveSinceModifiedEvent.php b/lib/Events/ActiveSinceModifiedEvent.php new file mode 100644 index 0000000000..e250899dee --- /dev/null +++ b/lib/Events/ActiveSinceModifiedEvent.php @@ -0,0 +1,12 @@ +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 diff --git a/lib/Federation/CloudFederationProviderTalk.php b/lib/Federation/CloudFederationProviderTalk.php index 1e035510a9..8d377932d3 100644 --- a/lib/Federation/CloudFederationProviderTalk.php +++ b/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); diff --git a/lib/Federation/Proxy/TalkV1/Notifier/RoomModifiedListener.php b/lib/Federation/Proxy/TalkV1/Notifier/RoomModifiedListener.php index da0ad98f46..8141173d58 100644 --- a/lib/Federation/Proxy/TalkV1/Notifier/RoomModifiedListener.php +++ b/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(), diff --git a/lib/Service/RoomService.php b/lib/Service/RoomService.php index 7ff5d5c420..eec1459826 100644 --- a/lib/Service/RoomService.php +++ b/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; }