From f004976effb2adc9f434796317914705c615bd64 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 10 Feb 2022 17:29:59 +0100 Subject: [PATCH 01/13] Handle all user status changes in case of "End meeting for all" in 1 execution Signed-off-by: Joas Schilling --- lib/Events/EndCallForEveryoneEvent.php | 18 ++++++++++++++++++ lib/Service/ParticipantService.php | 5 +++++ lib/Status/Listener.php | 21 +++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/lib/Events/EndCallForEveryoneEvent.php b/lib/Events/EndCallForEveryoneEvent.php index a080e5f0719..0693ceb9f1c 100644 --- a/lib/Events/EndCallForEveryoneEvent.php +++ b/lib/Events/EndCallForEveryoneEvent.php @@ -30,6 +30,8 @@ class EndCallForEveryoneEvent extends ModifyRoomEvent { /** @var string[] */ protected $sessionIds; + /** @var string[] */ + protected $userIds; public function __construct(Room $room, ?Participant $actor = null) { @@ -51,4 +53,20 @@ public function setSessionIds(array $sessionIds): void { public function getSessionIds(): array { return $this->sessionIds; } + + /** + * @param string[] $userIds + * @return void + */ + public function setUserIds(array $userIds): void { + $this->userIds = $userIds; + } + + /** + * Only available in the after-event + * @return string[] + */ + public function getUserIds(): array { + return $this->userIds; + } } diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index eb26ae2361f..24f8e4a3ab8 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -913,14 +913,19 @@ public function endCallForEveryone(Room $room, Participant $moderator): void { $participants = $this->getParticipantsInCall($room); $changedSessionIds = []; + $changedUserIds = []; // kick out all participants out of the call foreach ($participants as $participant) { $changedSessionIds[] = $participant->getSession()->getSessionId(); + if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) { + $changedUserIds[] = $participant->getAttendee()->getActorId(); + } $this->changeInCall($room, $participant, Participant::FLAG_DISCONNECTED, true); } $event->setSessionIds($changedSessionIds); + $event->setUserIds($changedUserIds); $this->dispatcher->dispatch(Room::EVENT_AFTER_END_CALL_FOR_EVERYONE, $event); } diff --git a/lib/Status/Listener.php b/lib/Status/Listener.php index a41953ea6ee..de585b76050 100644 --- a/lib/Status/Listener.php +++ b/lib/Status/Listener.php @@ -26,6 +26,8 @@ namespace OCA\Talk\Status; +use OCA\Talk\Events\EndCallForEveryoneEvent; +use OCA\Talk\Events\ModifyEveryoneEvent; use OCA\Talk\Events\ModifyParticipantEvent; use OCA\Talk\Model\Attendee; use OCA\Talk\Room; @@ -53,6 +55,12 @@ public static function register(IEventDispatcher $dispatcher): void { $listener = \OC::$server->get(self::class); $listener->revertUserStatus($event); }); + + $dispatcher->addListener(Room::EVENT_AFTER_END_CALL_FOR_EVERYONE, static function (EndCallForEveryoneEvent $event) { + /** @var self $listener */ + $listener = \OC::$server->get(self::class); + $listener->revertUserStatusOnEndCallForEveryone($event); + }); } public function setUserStatus(ModifyParticipantEvent $event): void { @@ -62,8 +70,21 @@ public function setUserStatus(ModifyParticipantEvent $event): void { } public function revertUserStatus(ModifyParticipantEvent $event): void { + if ($event instanceof ModifyEveryoneEvent) { + // Do not revert the status with 3 queries per user. + // We will update it in one go at the end. + return; + } + if ($event->getParticipant()->getAttendee()->getActorType() === Attendee::ACTOR_USERS) { $this->statusManager->revertUserStatus($event->getParticipant()->getAttendee()->getActorId(), 'call', IUserStatus::AWAY); } } + + public function revertUserStatusOnEndCallForEveryone(EndCallForEveryoneEvent $event): void { + $userIds = $event->getUserIds(); + if (!empty($userIds)) { + $this->statusManager->revertMultipleUserStatus($userIds, 'call', IUserStatus::AWAY); + } + } } From 904236d6f097877afd520f3dba267167cf874589 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 25 Feb 2022 21:02:07 +0100 Subject: [PATCH 02/13] Bump NC api lib Signed-off-by: Joas Schilling --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index e0ed9282b20..7f93588c6f6 100644 --- a/composer.lock +++ b/composer.lock @@ -179,12 +179,12 @@ "source": { "type": "git", "url": "https://github.com/ChristophWurst/nextcloud_composer.git", - "reference": "8d20160d6a06f4731acaee1989fd4f81c854ec9a" + "reference": "ed583894ecc139b3c8c687cf602e2113ff15ffb9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ChristophWurst/nextcloud_composer/zipball/8d20160d6a06f4731acaee1989fd4f81c854ec9a", - "reference": "8d20160d6a06f4731acaee1989fd4f81c854ec9a", + "url": "https://api.github.com/repos/ChristophWurst/nextcloud_composer/zipball/ed583894ecc139b3c8c687cf602e2113ff15ffb9", + "reference": "ed583894ecc139b3c8c687cf602e2113ff15ffb9", "shasum": "" }, "require": { @@ -215,7 +215,7 @@ "issues": "https://github.com/ChristophWurst/nextcloud_composer/issues", "source": "https://github.com/ChristophWurst/nextcloud_composer/tree/master" }, - "time": "2022-02-09T01:16:59+00:00" + "time": "2022-02-25T01:19:34+00:00" }, { "name": "composer/package-versions-deprecated", From 4fd2566a8c8bc13e1fb22ff494dccb9fc4820867 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 25 Feb 2022 15:58:13 +0100 Subject: [PATCH 03/13] Add an integration test for the company call case Signed-off-by: Joas Schilling --- .../features/callapi/company-call.feature | 430 ++++++++++++++++++ 1 file changed, 430 insertions(+) create mode 100644 tests/integration/features/callapi/company-call.feature diff --git a/tests/integration/features/callapi/company-call.feature b/tests/integration/features/callapi/company-call.feature new file mode 100644 index 00000000000..26639b7dde3 --- /dev/null +++ b/tests/integration/features/callapi/company-call.feature @@ -0,0 +1,430 @@ +Feature: callapi/company-call + Background: + Given group "company" exists + And user "employee1" exists + And user "employee1" is member of group "company" + And user "employee2" exists + And user "employee2" is member of group "company" + And user "employee3" exists + And user "employee3" is member of group "company" + And user "employee4" exists + And user "employee4" is member of group "company" + And user "employee5" exists + And user "employee5" is member of group "company" + And user "employee6" exists + And user "employee6" is member of group "company" + And user "employee7" exists + And user "employee7" is member of group "company" + And user "employee8" exists + And user "employee8" is member of group "company" + And user "employee9" exists + And user "employee9" is member of group "company" + And user "employee10" exists + And user "employee10" is member of group "company" + And user "employee11" exists + And user "employee11" is member of group "company" + And user "employee12" exists + And user "employee12" is member of group "company" + And user "employee13" exists + And user "employee13" is member of group "company" + And user "employee14" exists + And user "employee14" is member of group "company" + And user "employee15" exists + And user "employee15" is member of group "company" + And user "employee16" exists + And user "employee16" is member of group "company" + And user "employee17" exists + And user "employee17" is member of group "company" + And user "employee18" exists + And user "employee18" is member of group "company" + And user "employee19" exists + And user "employee19" is member of group "company" + And user "employee20" exists + And user "employee20" is member of group "company" + And user "employee21" exists + And user "employee21" is member of group "company" + And user "employee22" exists + And user "employee22" is member of group "company" + And user "employee23" exists + And user "employee23" is member of group "company" + And user "employee24" exists + And user "employee24" is member of group "company" + And user "employee25" exists + And user "employee25" is member of group "company" + And user "employee26" exists + And user "employee26" is member of group "company" + And user "employee27" exists + And user "employee27" is member of group "company" + And user "employee28" exists + And user "employee28" is member of group "company" + And user "employee29" exists + And user "employee29" is member of group "company" + And user "employee30" exists + And user "employee30" is member of group "company" + And user "employee31" exists + And user "employee31" is member of group "company" + And user "employee32" exists + And user "employee32" is member of group "company" + And user "employee33" exists + And user "employee33" is member of group "company" + And user "employee34" exists + And user "employee34" is member of group "company" + And user "employee35" exists + And user "employee35" is member of group "company" + And user "employee36" exists + And user "employee36" is member of group "company" + And user "employee37" exists + And user "employee37" is member of group "company" + And user "employee38" exists + And user "employee38" is member of group "company" + And user "employee39" exists + And user "employee39" is member of group "company" + And user "employee40" exists + And user "employee40" is member of group "company" + And user "employee41" exists + And user "employee41" is member of group "company" + And user "employee42" exists + And user "employee42" is member of group "company" + And user "employee43" exists + And user "employee43" is member of group "company" + And user "employee44" exists + And user "employee44" is member of group "company" + And user "employee45" exists + And user "employee45" is member of group "company" + And user "employee46" exists + And user "employee46" is member of group "company" + And user "employee47" exists + And user "employee47" is member of group "company" + And user "employee48" exists + And user "employee48" is member of group "company" + And user "employee49" exists + And user "employee49" is member of group "company" + And user "employee50" exists + And user "employee50" is member of group "company" + And user "employee51" exists + And user "employee51" is member of group "company" + And user "employee52" exists + And user "employee52" is member of group "company" + And user "employee53" exists + And user "employee53" is member of group "company" + And user "employee54" exists + And user "employee54" is member of group "company" + And user "employee55" exists + And user "employee55" is member of group "company" + And user "employee56" exists + And user "employee56" is member of group "company" + And user "employee57" exists + And user "employee57" is member of group "company" + And user "employee58" exists + And user "employee58" is member of group "company" + And user "employee59" exists + And user "employee59" is member of group "company" + And user "employee60" exists + And user "employee60" is member of group "company" + And user "employee61" exists + And user "employee61" is member of group "company" + And user "employee62" exists + And user "employee62" is member of group "company" + And user "employee63" exists + And user "employee63" is member of group "company" + And user "employee64" exists + And user "employee64" is member of group "company" + And user "employee65" exists + And user "employee65" is member of group "company" + And user "employee66" exists + And user "employee66" is member of group "company" + And user "employee67" exists + And user "employee67" is member of group "company" + And user "employee68" exists + And user "employee68" is member of group "company" + And user "employee69" exists + And user "employee69" is member of group "company" + And user "employee70" exists + And user "employee70" is member of group "company" + + Scenario: Company call + Then user "employee1" is participant of the following rooms (v4) + Then user "employee2" is participant of the following rooms (v4) + Then user "employee3" is participant of the following rooms (v4) + Then user "employee4" is participant of the following rooms (v4) + Then user "employee5" is participant of the following rooms (v4) + Then user "employee6" is participant of the following rooms (v4) + Then user "employee7" is participant of the following rooms (v4) + Then user "employee8" is participant of the following rooms (v4) + Then user "employee9" is participant of the following rooms (v4) + Then user "employee10" is participant of the following rooms (v4) + Then user "employee11" is participant of the following rooms (v4) + Then user "employee12" is participant of the following rooms (v4) + Then user "employee13" is participant of the following rooms (v4) + Then user "employee14" is participant of the following rooms (v4) + Then user "employee15" is participant of the following rooms (v4) + Then user "employee16" is participant of the following rooms (v4) + Then user "employee17" is participant of the following rooms (v4) + Then user "employee18" is participant of the following rooms (v4) + Then user "employee19" is participant of the following rooms (v4) + Then user "employee20" is participant of the following rooms (v4) + Then user "employee21" is participant of the following rooms (v4) + Then user "employee22" is participant of the following rooms (v4) + Then user "employee23" is participant of the following rooms (v4) + Then user "employee24" is participant of the following rooms (v4) + Then user "employee25" is participant of the following rooms (v4) + Then user "employee26" is participant of the following rooms (v4) + Then user "employee27" is participant of the following rooms (v4) + Then user "employee28" is participant of the following rooms (v4) + Then user "employee29" is participant of the following rooms (v4) + Then user "employee30" is participant of the following rooms (v4) + Then user "employee31" is participant of the following rooms (v4) + Then user "employee32" is participant of the following rooms (v4) + Then user "employee33" is participant of the following rooms (v4) + Then user "employee34" is participant of the following rooms (v4) + Then user "employee35" is participant of the following rooms (v4) + Then user "employee36" is participant of the following rooms (v4) + Then user "employee37" is participant of the following rooms (v4) + Then user "employee38" is participant of the following rooms (v4) + Then user "employee39" is participant of the following rooms (v4) + Then user "employee40" is participant of the following rooms (v4) + Then user "employee41" is participant of the following rooms (v4) + Then user "employee42" is participant of the following rooms (v4) + Then user "employee43" is participant of the following rooms (v4) + Then user "employee44" is participant of the following rooms (v4) + Then user "employee45" is participant of the following rooms (v4) + Then user "employee46" is participant of the following rooms (v4) + Then user "employee47" is participant of the following rooms (v4) + Then user "employee48" is participant of the following rooms (v4) + Then user "employee49" is participant of the following rooms (v4) + Then user "employee50" is participant of the following rooms (v4) + Then user "employee51" is participant of the following rooms (v4) + Then user "employee52" is participant of the following rooms (v4) + Then user "employee53" is participant of the following rooms (v4) + Then user "employee54" is participant of the following rooms (v4) + Then user "employee55" is participant of the following rooms (v4) + Then user "employee56" is participant of the following rooms (v4) + Then user "employee57" is participant of the following rooms (v4) + Then user "employee58" is participant of the following rooms (v4) + Then user "employee59" is participant of the following rooms (v4) + Then user "employee60" is participant of the following rooms (v4) + Then user "employee61" is participant of the following rooms (v4) + Then user "employee62" is participant of the following rooms (v4) + Then user "employee63" is participant of the following rooms (v4) + Then user "employee64" is participant of the following rooms (v4) + Then user "employee65" is participant of the following rooms (v4) + Then user "employee66" is participant of the following rooms (v4) + Then user "employee67" is participant of the following rooms (v4) + Then user "employee68" is participant of the following rooms (v4) + Then user "employee69" is participant of the following rooms (v4) + Then user "employee70" is participant of the following rooms (v4) + When user "employee1" creates room "room" (v4) + | roomType | 2 | + | invite | company | + When user "employee1" sets default permissions for room "room" to "CJ" with 200 (v4) + Then user "employee1" joins room "room" with 200 (v4) + Then user "employee1" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee2" joins room "room" with 200 (v4) + Then user "employee2" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee3" joins room "room" with 200 (v4) + Then user "employee3" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee4" joins room "room" with 200 (v4) + Then user "employee4" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee5" joins room "room" with 200 (v4) + Then user "employee5" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee6" joins room "room" with 200 (v4) + Then user "employee6" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee7" joins room "room" with 200 (v4) + Then user "employee7" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee8" joins room "room" with 200 (v4) + Then user "employee8" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee9" joins room "room" with 200 (v4) + Then user "employee9" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee10" joins room "room" with 200 (v4) + Then user "employee10" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee11" joins room "room" with 200 (v4) + Then user "employee11" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee12" joins room "room" with 200 (v4) + Then user "employee12" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee13" joins room "room" with 200 (v4) + Then user "employee13" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee14" joins room "room" with 200 (v4) + Then user "employee14" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee15" joins room "room" with 200 (v4) + Then user "employee15" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee16" joins room "room" with 200 (v4) + Then user "employee16" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee17" joins room "room" with 200 (v4) + Then user "employee17" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee18" joins room "room" with 200 (v4) + Then user "employee18" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee19" joins room "room" with 200 (v4) + Then user "employee19" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee20" joins room "room" with 200 (v4) + Then user "employee20" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee21" joins room "room" with 200 (v4) + Then user "employee21" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee22" joins room "room" with 200 (v4) + Then user "employee22" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee23" joins room "room" with 200 (v4) + Then user "employee23" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee24" joins room "room" with 200 (v4) + Then user "employee24" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee25" joins room "room" with 200 (v4) + Then user "employee25" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee26" joins room "room" with 200 (v4) + Then user "employee26" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee27" joins room "room" with 200 (v4) + Then user "employee27" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee28" joins room "room" with 200 (v4) + Then user "employee28" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee29" joins room "room" with 200 (v4) + Then user "employee29" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee30" joins room "room" with 200 (v4) + Then user "employee30" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee31" joins room "room" with 200 (v4) + Then user "employee31" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee32" joins room "room" with 200 (v4) + Then user "employee32" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee33" joins room "room" with 200 (v4) + Then user "employee33" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee34" joins room "room" with 200 (v4) + Then user "employee34" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee35" joins room "room" with 200 (v4) + Then user "employee35" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee36" joins room "room" with 200 (v4) + Then user "employee36" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee37" joins room "room" with 200 (v4) + Then user "employee37" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee38" joins room "room" with 200 (v4) + Then user "employee38" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee39" joins room "room" with 200 (v4) + Then user "employee39" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee40" joins room "room" with 200 (v4) + Then user "employee40" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee41" joins room "room" with 200 (v4) + Then user "employee41" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee42" joins room "room" with 200 (v4) + Then user "employee42" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee43" joins room "room" with 200 (v4) + Then user "employee43" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee44" joins room "room" with 200 (v4) + Then user "employee44" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee45" joins room "room" with 200 (v4) + Then user "employee45" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee46" joins room "room" with 200 (v4) + Then user "employee46" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee47" joins room "room" with 200 (v4) + Then user "employee47" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee48" joins room "room" with 200 (v4) + Then user "employee48" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee49" joins room "room" with 200 (v4) + Then user "employee49" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee50" joins room "room" with 200 (v4) + Then user "employee50" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee51" joins room "room" with 200 (v4) + Then user "employee51" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee52" joins room "room" with 200 (v4) + Then user "employee52" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee53" joins room "room" with 200 (v4) + Then user "employee53" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee54" joins room "room" with 200 (v4) + Then user "employee54" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee55" joins room "room" with 200 (v4) + Then user "employee55" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee56" joins room "room" with 200 (v4) + Then user "employee56" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee57" joins room "room" with 200 (v4) + Then user "employee57" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee58" joins room "room" with 200 (v4) + Then user "employee58" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee59" joins room "room" with 200 (v4) + Then user "employee59" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee60" joins room "room" with 200 (v4) + Then user "employee60" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee61" joins room "room" with 200 (v4) + Then user "employee61" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee62" joins room "room" with 200 (v4) + Then user "employee62" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee63" joins room "room" with 200 (v4) + Then user "employee63" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee64" joins room "room" with 200 (v4) + Then user "employee64" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee65" joins room "room" with 200 (v4) + Then user "employee65" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee66" joins room "room" with 200 (v4) + Then user "employee66" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee67" joins room "room" with 200 (v4) + Then user "employee67" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee68" joins room "room" with 200 (v4) + Then user "employee68" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee69" joins room "room" with 200 (v4) + Then user "employee69" joins call "room" with 200 (v4) + | flags | 1 | + Then user "employee70" joins room "room" with 200 (v4) + Then user "employee70" joins call "room" with 200 (v4) + | flags | 1 | + When user "employee1" ends call "room" with 200 (v4) From b30d0ea71805941b5a5ec3ef6dc99d32f47d5d8b Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 26 Feb 2022 00:20:08 +0100 Subject: [PATCH 04/13] Reset all in_call flags in one go Signed-off-by: Joas Schilling --- lib/Model/SessionMapper.php | 12 ++++++++++++ lib/Service/ParticipantService.php | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/Model/SessionMapper.php b/lib/Model/SessionMapper.php index 1b747eace1d..0c14d678e37 100644 --- a/lib/Model/SessionMapper.php +++ b/lib/Model/SessionMapper.php @@ -23,6 +23,7 @@ namespace OCA\Talk\Model; +use OCA\Talk\Participant; use OCP\AppFramework\Db\QBMapper; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; @@ -90,6 +91,17 @@ public function deleteByIds(array $ids): int { return $delete->executeStatement(); } + /** + * @param int[] $ids + */ + public function resetInCallByIds(array $ids): void { + $update = $this->db->getQueryBuilder(); + $update->update($this->getTableName()) + ->set('in_call', $update->createNamedParameter(Participant::FLAG_DISCONNECTED, IQueryBuilder::PARAM_INT)) + ->where($update->expr()->in('id', $update->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY))); + $update->executeStatement(); + } + public function createSessionFromRow(array $row): Session { return $this->mapRowToEntity([ 'id' => $row['s_id'], diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 24f8e4a3ab8..960330cee28 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -924,6 +924,8 @@ public function endCallForEveryone(Room $room, Participant $moderator): void { $this->changeInCall($room, $participant, Participant::FLAG_DISCONNECTED, true); } + $this->sessionMapper->resetInCallByIds($changedSessionIds); + $event->setSessionIds($changedSessionIds); $event->setUserIds($changedUserIds); @@ -957,7 +959,9 @@ public function changeInCall(Room $room, Participant $participant, int $flags, b } $session->setInCall($flags); - $this->sessionMapper->update($session); + if (!$endCallForEveryone) { + $this->sessionMapper->update($session); + } if ($flags !== Participant::FLAG_DISCONNECTED) { $attendee = $participant->getAttendee(); From 8c12796b0d276bce3c7fbddc1416dc803925094b Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 26 Feb 2022 00:20:48 +0100 Subject: [PATCH 05/13] Need to be combined with setLastMessage and delayed Currently there are 142 queries when adding a group with 70 users instead of 1 query updating both values at the end. Signed-off-by: Joas Schilling --- lib/Room.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Room.php b/lib/Room.php index d8520258d8d..16e2f3f5991 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -768,6 +768,7 @@ public function setPassword(string $password): bool { * @return bool */ public function setLastActivity(\DateTime $now): bool { + // FIXME combine with setLastMessage and delay in case of multiple system messages $update = $this->db->getQueryBuilder(); $update->update('talk_rooms') ->set('last_activity', $update->createNamedParameter($now, 'datetime')) From 114a9dda2fa18323162ce3bdbd9a929398726351 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 26 Feb 2022 00:21:47 +0100 Subject: [PATCH 06/13] Only calculate the room name once instead of loading all participants Signed-off-by: Joas Schilling --- lib/Activity/Listener.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/Activity/Listener.php b/lib/Activity/Listener.php index 232225b6826..57410417ff6 100644 --- a/lib/Activity/Listener.php +++ b/lib/Activity/Listener.php @@ -232,6 +232,11 @@ public function generateInvitationActivity(Room $room, array $participants): voi return; } + // We know the new participant is in the room, + // so skip loading them just to make sure they can read it. + // Must be overwritten later on for one-to-one chats. + $roomName = $room->getDisplayName($actorId); + foreach ($participants as $participant) { if ($participant['actorType'] !== Attendee::ACTOR_USERS) { // No user => no activity @@ -244,7 +249,10 @@ public function generateInvitationActivity(Room $room, array $participants): voi } try { - $roomName = $room->getDisplayName($participant['actorId']); + if ($room->getType() === Room::TYPE_ONE_TO_ONE) { + // Overwrite the room name with the other participant + $roomName = $room->getDisplayName($participant['actorId']); + } $event ->setObject('room', $room->getId(), $roomName) ->setSubject('invitation', [ From d32e490b2966ebd8a3310e19beeaf5516d162f33 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 26 Feb 2022 22:21:00 +0100 Subject: [PATCH 07/13] fixup! Need to be combined with setLastMessage and delayed --- lib/AppInfo/Application.php | 4 ++++ lib/Chat/ChatManager.php | 13 ++++++++----- lib/Chat/SystemMessage/Listener.php | 19 +++++++++++++++---- lib/Events/AddParticipantsEvent.php | 22 +++++++++++++++++++++- lib/Events/ChatEvent.php | 11 ++++++++++- lib/Service/ParticipantService.php | 24 ++++++++++++++++++++++-- 6 files changed, 80 insertions(+), 13 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 24075635bfb..a9163663502 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -217,6 +217,10 @@ protected function registerNavigationLink(IServerContainer $server): void { protected function registerRoomActivityHooks(IEventDispatcher $dispatcher): void { $listener = function (ChatEvent $event): void { + if ($event->shouldSkipLastActivityUpdate()) { + return; + } + $room = $event->getRoom(); /** @var ITimeFactory $timeFactory */ $timeFactory = $this->getContainer()->query(ITimeFactory::class); diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php index 31511683567..9c6d44f3063 100644 --- a/lib/Chat/ChatManager.php +++ b/lib/Chat/ChatManager.php @@ -128,7 +128,8 @@ public function addSystemMessage( \DateTime $creationDateTime, bool $sendNotifications, ?string $referenceId = null, - ?int $parentId = null + ?int $parentId = null, + bool $shouldSkipLastMessageUpdate = false ): IComment { $comment = $this->commentsManager->create($actorType, $actorId, 'chat', (string) $chat->getId()); $comment->setMessage($message, self::MAX_CHAT_LENGTH); @@ -152,14 +153,16 @@ public function addSystemMessage( $comment->setVerb('system'); } - $event = new ChatEvent($chat, $comment); + $event = new ChatEvent($chat, $comment, $shouldSkipLastMessageUpdate); $this->dispatcher->dispatch(self::EVENT_BEFORE_SYSTEM_MESSAGE_SEND, $event); try { $this->commentsManager->save($comment); - // Update last_message - $chat->setLastMessage($comment); - $this->unreadCountCache->clear($chat->getId() . '-'); + if (!$shouldSkipLastMessageUpdate) { + // Update last_message + $chat->setLastMessage($comment); + $this->unreadCountCache->clear($chat->getId() . '-'); + } if ($sendNotifications) { $this->notifier->notifyOtherParticipant($chat, $comment, []); diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php index 0ecbd4636d0..2308b061b9c 100644 --- a/lib/Chat/SystemMessage/Listener.php +++ b/lib/Chat/SystemMessage/Listener.php @@ -43,6 +43,7 @@ use OCA\Talk\TalkSession; use OCA\Talk\Webinary; use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Comments\IComment; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventDispatcher; use OCP\EventDispatcher\IEventListener; @@ -263,7 +264,15 @@ public static function register(IEventDispatcher $dispatcher): void { || $listener->getUserId() !== $participant['actorId'] // - has joined a listable room on their own || $participantType === Participant::USER) { - $listener->sendSystemMessage($room, 'user_added', ['user' => $participant['actorId']]); + $comment = $listener->sendSystemMessage( + $room, + 'user_added', + ['user' => $participant['actorId']], + null, + $event->shouldSkipLastMessageUpdate() + ); + + $event->setLastMessage($comment); } } }); @@ -379,7 +388,7 @@ protected function attendeesRemovedEvent(AttendeesRemovedEvent $event): void { } } - protected function sendSystemMessage(Room $room, string $message, array $parameters = [], Participant $participant = null): void { + protected function sendSystemMessage(Room $room, string $message, array $parameters = [], Participant $participant = null, bool $shouldSkipLastMessageUpdate = false): IComment { if ($participant instanceof Participant) { $actorType = $participant->getAttendee()->getActorType(); $actorId = $participant->getAttendee()->getActorId(); @@ -408,11 +417,13 @@ protected function sendSystemMessage(Room $room, string $message, array $paramet $referenceId = (string) $referenceId; } - $this->chatManager->addSystemMessage( + return $this->chatManager->addSystemMessage( $room, $actorType, $actorId, json_encode(['message' => $message, 'parameters' => $parameters]), $this->timeFactory->getDateTime(), $message === 'file_shared', - $referenceId + $referenceId, + null, + $shouldSkipLastMessageUpdate ); } diff --git a/lib/Events/AddParticipantsEvent.php b/lib/Events/AddParticipantsEvent.php index 5d214bfb2a0..f05c0235433 100644 --- a/lib/Events/AddParticipantsEvent.php +++ b/lib/Events/AddParticipantsEvent.php @@ -24,17 +24,25 @@ namespace OCA\Talk\Events; use OCA\Talk\Room; +use OCP\Comments\IComment; class AddParticipantsEvent extends RoomEvent { /** @var array */ protected $participants; + /** @var bool */ + protected $skipLastMessageUpdate; + + /** @var IComment|null */ + protected $lastMessage; public function __construct(Room $room, - array $participants) { + array $participants, + bool $skipLastMessageUpdate = false) { parent::__construct($room); $this->participants = $participants; + $this->skipLastMessageUpdate = $skipLastMessageUpdate; } /** @@ -43,4 +51,16 @@ public function __construct(Room $room, public function getParticipants(): array { return $this->participants; } + + public function shouldSkipLastMessageUpdate(): bool { + return $this->skipLastMessageUpdate; + } + + public function setLastMessage(IComment $lastMessage): void { + $this->lastMessage = $lastMessage; + } + + public function getLastMessage(): ?IComment { + return $this->lastMessage; + } } diff --git a/lib/Events/ChatEvent.php b/lib/Events/ChatEvent.php index 2a9e548e298..40d11f24aa7 100644 --- a/lib/Events/ChatEvent.php +++ b/lib/Events/ChatEvent.php @@ -31,13 +31,22 @@ class ChatEvent extends RoomEvent { /** @var IComment */ protected $comment; + /** @var bool */ + protected $skipLastActivityUpdate; - public function __construct(Room $room, IComment $comment) { + public function __construct(Room $room, + IComment $comment, + bool $skipLastActivityUpdate = false) { parent::__construct($room); $this->comment = $comment; + $this->skipLastActivityUpdate = $skipLastActivityUpdate; } public function getComment(): IComment { return $this->comment; } + + public function shouldSkipLastActivityUpdate(): bool { + return $this->skipLastActivityUpdate; + } } diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 960330cee28..9de5742b0c8 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -23,6 +23,7 @@ namespace OCA\Talk\Service; +use Aws\IoT1ClickDevicesService\IoT1ClickDevicesServiceClient; use OCA\Circles\CirclesManager; use OCA\Circles\Model\Circle; use OCA\Circles\Model\Member; @@ -59,6 +60,7 @@ use OCP\DB\Exception; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IDBConnection; use OCP\IGroup; @@ -94,6 +96,8 @@ class ParticipantService { private $notifications; /** @var ITimeFactory */ private $timeFactory; + /** @var ICacheFactory */ + private $cacheFactory; public function __construct(IConfig $serverConfig, Config $talkConfig, @@ -107,7 +111,8 @@ public function __construct(IConfig $serverConfig, IGroupManager $groupManager, MembershipService $membershipService, Notifications $notifications, - ITimeFactory $timeFactory) { + ITimeFactory $timeFactory, + ICacheFactory $cacheFactory) { $this->serverConfig = $serverConfig; $this->talkConfig = $talkConfig; $this->attendeeMapper = $attendeeMapper; @@ -120,6 +125,7 @@ public function __construct(IConfig $serverConfig, $this->groupManager = $groupManager; $this->membershipService = $membershipService; $this->timeFactory = $timeFactory; + $this->cacheFactory = $cacheFactory; $this->notifications = $notifications; } @@ -367,7 +373,7 @@ public function addUsers(Room $room, array $participants, ?IUser $addedBy = null if (empty($participants)) { return; } - $event = new AddParticipantsEvent($room, $participants); + $event = new AddParticipantsEvent($room, $participants, true); $this->dispatcher->dispatch(Room::EVENT_BEFORE_USERS_ADD, $event); $lastMessage = 0; @@ -426,9 +432,23 @@ public function addUsers(Room $room, array $participants, ?IUser $addedBy = null $this->dispatcher->dispatchTyped($attendeeEvent); $this->dispatcher->dispatch(Room::EVENT_AFTER_USERS_ADD, $event); + + $lastMessage = $event->getLastMessage(); + if ($lastMessage instanceof IComment) { + $this->updateRoomLastMessage($room, $lastMessage); + } } } + protected function updateRoomLastMessage(Room $room, IComment $message): void { + $room->setLastMessage($message); + $room->setLastActivity($message->getCreationDateTime()); + $lastMessageCache = $this->cacheFactory->createDistributed('talk/lastmsgid'); + $lastMessageCache->remove($room->getToken()); + $unreadCountCache = $this->cacheFactory->createDistributed('talk/unreadcount'); + $unreadCountCache->clear($room->getId() . '-'); + } + public function getHighestPermissionAttendee(Room $room): ?Attendee { try { $roomOwners = $this->attendeeMapper->getActorsByParticipantTypes($room->getId(), [Participant::OWNER]); From 3925520f0da25350d3bf90e15f0ebda583f33540 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 26 Feb 2022 22:29:57 +0100 Subject: [PATCH 08/13] Combine last_activity and last_message update where possible Signed-off-by: Joas Schilling --- lib/AppInfo/Application.php | 19 ------------------- lib/Chat/ChatManager.php | 2 ++ lib/Room.php | 3 ++- lib/Service/ParticipantService.php | 1 - 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index a9163663502..3cffc17238a 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -42,7 +42,6 @@ use OCA\Talk\Deck\DeckPluginLoader; use OCA\Talk\Events\AttendeesAddedEvent; use OCA\Talk\Events\AttendeesRemovedEvent; -use OCA\Talk\Events\ChatEvent; use OCA\Talk\Events\RoomEvent; use OCA\Talk\Federation\CloudFederationProviderTalk; use OCA\Talk\Files\Listener as FilesListener; @@ -82,7 +81,6 @@ use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\AppFramework\IAppContainer; -use OCP\AppFramework\Utility\ITimeFactory; use OCP\Collaboration\Resources\IProviderManager; use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\ICloudFederationProvider; @@ -172,7 +170,6 @@ public function boot(IBootContext $context): void { ShareListener::register($dispatcher); StatusListener::register($dispatcher); - $this->registerRoomActivityHooks($dispatcher); $this->registerChatHooks($dispatcher); $context->injectFn(\Closure::fromCallable([$this, 'registerCloudFederationProviderManager'])); } @@ -215,22 +212,6 @@ protected function registerNavigationLink(IServerContainer $server): void { }); } - protected function registerRoomActivityHooks(IEventDispatcher $dispatcher): void { - $listener = function (ChatEvent $event): void { - if ($event->shouldSkipLastActivityUpdate()) { - return; - } - - $room = $event->getRoom(); - /** @var ITimeFactory $timeFactory */ - $timeFactory = $this->getContainer()->query(ITimeFactory::class); - $room->setLastActivity($timeFactory->getDateTime()); - }; - - $dispatcher->addListener(ChatManager::EVENT_AFTER_MESSAGE_SEND, $listener); - $dispatcher->addListener(ChatManager::EVENT_AFTER_SYSTEM_MESSAGE_SEND, $listener); - } - protected function registerChatHooks(IEventDispatcher $dispatcher): void { $listener = function (RoomEvent $event): void { /** @var ChatManager $chatManager */ diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php index 9c6d44f3063..dba31669102 100644 --- a/lib/Chat/ChatManager.php +++ b/lib/Chat/ChatManager.php @@ -248,6 +248,8 @@ public function sendMessage(Room $chat, Participant $participant, string $actorT if ($comment->getActorType() !== 'bots' || $comment->getActorId() === 'changelog') { $chat->setLastMessage($comment); $this->unreadCountCache->clear($chat->getId() . '-'); + } else { + $chat->setLastActivity($comment->getCreationDateTime()); } $alreadyNotifiedUsers = []; diff --git a/lib/Room.php b/lib/Room.php index 16e2f3f5991..f9cdc1c1932 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -768,7 +768,6 @@ public function setPassword(string $password): bool { * @return bool */ public function setLastActivity(\DateTime $now): bool { - // FIXME combine with setLastMessage and delay in case of multiple system messages $update = $this->db->getQueryBuilder(); $update->update('talk_rooms') ->set('last_activity', $update->createNamedParameter($now, 'datetime')) @@ -830,11 +829,13 @@ public function setLastMessage(IComment $message): void { $update = $this->db->getQueryBuilder(); $update->update('talk_rooms') ->set('last_message', $update->createNamedParameter((int) $message->getId())) + ->set('last_activity', $update->createNamedParameter($message->getCreationDateTime(), 'datetime')) ->where($update->expr()->eq('id', $update->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT))); $update->executeStatement(); $this->lastMessage = $message; $this->lastMessageId = (int) $message->getId(); + $this->lastActivity = $message->getCreationDateTime(); } public function resetActiveSince(): bool { diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 9de5742b0c8..dfdc2e08999 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -442,7 +442,6 @@ public function addUsers(Room $room, array $participants, ?IUser $addedBy = null protected function updateRoomLastMessage(Room $room, IComment $message): void { $room->setLastMessage($message); - $room->setLastActivity($message->getCreationDateTime()); $lastMessageCache = $this->cacheFactory->createDistributed('talk/lastmsgid'); $lastMessageCache->remove($room->getToken()); $unreadCountCache = $this->cacheFactory->createDistributed('talk/unreadcount'); From 222dd2a3605e8c877cc50dde55ea21204897f370 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 2 Mar 2022 14:20:47 +0100 Subject: [PATCH 09/13] Emit a event so the HPB can send the update to the participants Signed-off-by: Joas Schilling --- lib/Chat/ChatManager.php | 1 + lib/Service/ParticipantService.php | 5 +++ lib/Signaling/Listener.php | 56 +++++++++++++----------------- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php index dba31669102..3c15c694cb7 100644 --- a/lib/Chat/ChatManager.php +++ b/lib/Chat/ChatManager.php @@ -57,6 +57,7 @@ class ChatManager { public const EVENT_BEFORE_SYSTEM_MESSAGE_SEND = self::class . '::preSendSystemMessage'; public const EVENT_AFTER_SYSTEM_MESSAGE_SEND = self::class . '::postSendSystemMessage'; + public const EVENT_AFTER_MULTIPLE_SYSTEM_MESSAGE_SEND = self::class . '::postSendMultipleSystemMessage'; public const EVENT_BEFORE_MESSAGE_SEND = self::class . '::preSendMessage'; public const EVENT_AFTER_MESSAGE_SEND = self::class . '::postSendMessage'; diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index dfdc2e08999..9f230c1a208 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -27,10 +27,12 @@ use OCA\Circles\CirclesManager; use OCA\Circles\Model\Circle; use OCA\Circles\Model\Member; +use OCA\Talk\Chat\ChatManager; use OCA\Talk\Config; use OCA\Talk\Events\AddParticipantsEvent; use OCA\Talk\Events\AttendeesAddedEvent; use OCA\Talk\Events\AttendeesRemovedEvent; +use OCA\Talk\Events\ChatEvent; use OCA\Talk\Events\EndCallForEveryoneEvent; use OCA\Talk\Events\JoinRoomGuestEvent; use OCA\Talk\Events\JoinRoomUserEvent; @@ -446,6 +448,9 @@ protected function updateRoomLastMessage(Room $room, IComment $message): void { $lastMessageCache->remove($room->getToken()); $unreadCountCache = $this->cacheFactory->createDistributed('talk/unreadcount'); $unreadCountCache->clear($room->getId() . '-'); + + $event = new ChatEvent($room, $message); + $this->dispatcher->dispatch(ChatManager::EVENT_AFTER_MULTIPLE_SYSTEM_MESSAGE_SEND, $event); } public function getHighestPermissionAttendee(Room $room): ?Attendee { diff --git a/lib/Signaling/Listener.php b/lib/Signaling/Listener.php index 2d603e2af02..e20cb85a01a 100644 --- a/lib/Signaling/Listener.php +++ b/lib/Signaling/Listener.php @@ -323,39 +323,31 @@ protected static function registerExternalSignaling(IEventDispatcher $dispatcher $notifier->participantsModified($event->getRoom(), $sessionIds); } }); - $dispatcher->addListener(ChatManager::EVENT_AFTER_MESSAGE_SEND, static function (ChatParticipantEvent $event) { - if (self::isUsingInternalSignaling()) { - return; - } - /** @var BackendNotifier $notifier */ - $notifier = \OC::$server->get(BackendNotifier::class); - - $room = $event->getRoom(); - $message = [ - 'type' => 'chat', - 'chat' => [ - 'refresh' => true, - ], - ]; - $notifier->sendRoomMessage($room, $message); - }); - $dispatcher->addListener(ChatManager::EVENT_AFTER_SYSTEM_MESSAGE_SEND, static function (ChatEvent $event) { - if (self::isUsingInternalSignaling()) { - return; - } - - /** @var BackendNotifier $notifier */ - $notifier = \OC::$server->get(BackendNotifier::class); + $dispatcher->addListener(ChatManager::EVENT_AFTER_MESSAGE_SEND, [self::class, 'chatListener']); + $dispatcher->addListener(ChatManager::EVENT_AFTER_SYSTEM_MESSAGE_SEND, [self::class, 'chatListener']); + $dispatcher->addListener(ChatManager::EVENT_AFTER_MULTIPLE_SYSTEM_MESSAGE_SEND, [self::class, 'chatListener']); + } - $room = $event->getRoom(); - $message = [ - 'type' => 'chat', - 'chat' => [ - 'refresh' => true, - ], - ]; - $notifier->sendRoomMessage($room, $message); - }); + public static function chatListener(ChatEvent $event): void { + if (self::isUsingInternalSignaling()) { + return; + } + + if ($event->shouldSkipLastActivityUpdate()) { + return; + } + + /** @var BackendNotifier $notifier */ + $notifier = \OC::$server->get(BackendNotifier::class); + + $room = $event->getRoom(); + $message = [ + 'type' => 'chat', + 'chat' => [ + 'refresh' => true, + ], + ]; + $notifier->sendRoomMessage($room, $message); } } From dc54521036647b8fd74cbd3c8acba2fa3622eb38 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 4 Mar 2022 11:59:49 +0100 Subject: [PATCH 10/13] Deduplicate getting the room and participant in case some annotations are combined Signed-off-by: Joas Schilling --- lib/Middleware/InjectionMiddleware.php | 40 +++++++++++++++----------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/lib/Middleware/InjectionMiddleware.php b/lib/Middleware/InjectionMiddleware.php index b4b0740039a..ab4617b830b 100644 --- a/lib/Middleware/InjectionMiddleware.php +++ b/lib/Middleware/InjectionMiddleware.php @@ -151,26 +151,32 @@ protected function getLoggedIn(AEnvironmentAwareController $controller, bool $mo * @throws ParticipantNotFoundException */ protected function getLoggedInOrGuest(AEnvironmentAwareController $controller, bool $moderatorRequired): void { - $token = $this->request->getParam('token'); - $sessionId = $this->talkSession->getSessionForRoom($token); - $room = $this->manager->getRoomForUserByToken($token, $this->userId, $sessionId); - $controller->setRoom($room); - $participant = null; - - if ($sessionId !== null) { - try { - $participant = $room->getParticipantBySession($sessionId); - } catch (ParticipantNotFoundException $e) { - // ignore and fall back in case a concurrent request might have - // invalidated the session - } + $room = $controller->getRoom(); + if (!$room instanceof Room) { + $token = $this->request->getParam('token'); + $sessionId = $this->talkSession->getSessionForRoom($token); + $room = $this->manager->getRoomForUserByToken($token, $this->userId, $sessionId); + $controller->setRoom($room); } - if ($participant === null) { - $participant = $room->getParticipant($this->userId); - } + $participant = $controller->getParticipant(); + if (!$participant instanceof Participant) { + $participant = null; + if ($sessionId !== null) { + try { + $participant = $room->getParticipantBySession($sessionId); + } catch (ParticipantNotFoundException $e) { + // ignore and fall back in case a concurrent request might have + // invalidated the session + } + } - $controller->setParticipant($participant); + if ($participant === null) { + $participant = $room->getParticipant($this->userId); + } + + $controller->setParticipant($participant); + } if ($moderatorRequired && !$participant->hasModeratorPermissions()) { throw new NotAModeratorException(); From 6f3f404c73704a904f1817e33b23ce76858fbfc2 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 4 Mar 2022 12:06:24 +0100 Subject: [PATCH 11/13] Inject the room instead of querying it over and over again Signed-off-by: Joas Schilling --- lib/Chat/Notifier.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/Chat/Notifier.php b/lib/Chat/Notifier.php index e8428ebba55..f9602151eff 100644 --- a/lib/Chat/Notifier.php +++ b/lib/Chat/Notifier.php @@ -104,8 +104,9 @@ public function notifyMentionedUsers(Room $chat, IComment $comment, array $alrea } $notification = $this->createNotification($chat, $comment, 'mention'); $shouldFlush = $this->notificationManager->defer(); + foreach ($usersToNotify as $mentionedUser) { - if ($this->shouldMentionedUserBeNotified($mentionedUser['id'], $comment)) { + if ($this->shouldMentionedUserBeNotified($mentionedUser['id'], $comment, $chat)) { $notification->setUser($mentionedUser['id']); $this->notificationManager->notify($notification); $alreadyNotifiedUsers[] = $mentionedUser; @@ -210,7 +211,7 @@ public function notifyReplyToAuthor(Room $chat, IComment $comment, IComment $rep return []; } - if (!$this->shouldMentionedUserBeNotified($replyTo->getActorId(), $comment)) { + if (!$this->shouldMentionedUserBeNotified($replyTo->getActorId(), $comment, $chat)) { return []; } @@ -426,9 +427,10 @@ protected function getDefaultGroupNotification(): int { * * @param string $userId * @param IComment $comment + * @param Room $room * @return bool */ - protected function shouldMentionedUserBeNotified(string $userId, IComment $comment): bool { + protected function shouldMentionedUserBeNotified(string $userId, IComment $comment, Room $room): bool { if ($comment->getActorType() === Attendee::ACTOR_USERS && $userId === $comment->getActorId()) { // Do not notify the user if they mentioned themselves return false; @@ -438,12 +440,6 @@ protected function shouldMentionedUserBeNotified(string $userId, IComment $comme return false; } - try { - $room = $this->manager->getRoomById((int) $comment->getObjectId()); - } catch (RoomNotFoundException $e) { - return false; - } - try { $participant = $room->getParticipant($userId, false); $notificationLevel = $participant->getAttendee()->getNotificationLevel(); From f22cf584e991521a16ec498cfe71a8b922c822ca Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 4 Mar 2022 12:23:40 +0100 Subject: [PATCH 12/13] Inject the attendee as well when loaded already Signed-off-by: Joas Schilling --- lib/Chat/Notifier.php | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/Chat/Notifier.php b/lib/Chat/Notifier.php index f9602151eff..6f1fb4f2261 100644 --- a/lib/Chat/Notifier.php +++ b/lib/Chat/Notifier.php @@ -106,7 +106,7 @@ public function notifyMentionedUsers(Room $chat, IComment $comment, array $alrea $shouldFlush = $this->notificationManager->defer(); foreach ($usersToNotify as $mentionedUser) { - if ($this->shouldMentionedUserBeNotified($mentionedUser['id'], $comment, $chat)) { + if ($this->shouldMentionedUserBeNotified($mentionedUser['id'], $comment, $chat, $mentionedUser['attendee'] ?? null)) { $notification->setUser($mentionedUser['id']); $this->notificationManager->notify($notification); $alreadyNotifiedUsers[] = $mentionedUser; @@ -171,18 +171,19 @@ private function addMentionAllToList(Room $chat, array $list): array { return $usersToNotify; } - $chatParticipants = $this->participantService->getActorsByType($chat, Attendee::ACTOR_USERS); - foreach ($chatParticipants as $participant) { - $alreadyAddedToNotify = array_filter($list, static function ($user) use ($participant): bool { - return $user['id'] === $participant->getActorId(); + $attendees = $this->participantService->getActorsByType($chat, Attendee::ACTOR_USERS); + foreach ($attendees as $attendee) { + $alreadyAddedToNotify = array_filter($list, static function ($user) use ($attendee): bool { + return $user['id'] === $attendee->getActorId(); }); if (!empty($alreadyAddedToNotify)) { continue; } $usersToNotify[] = [ - 'id' => $participant->getActorId(), - 'type' => $participant->getActorType() + 'id' => $attendee->getActorId(), + 'type' => $attendee->getActorType(), + 'attendee' => $attendee, ]; } @@ -428,21 +429,26 @@ protected function getDefaultGroupNotification(): int { * @param string $userId * @param IComment $comment * @param Room $room + * @param Attendee|null $attendee * @return bool */ - protected function shouldMentionedUserBeNotified(string $userId, IComment $comment, Room $room): bool { + protected function shouldMentionedUserBeNotified(string $userId, IComment $comment, Room $room, ?Attendee $attendee = null): bool { if ($comment->getActorType() === Attendee::ACTOR_USERS && $userId === $comment->getActorId()) { // Do not notify the user if they mentioned themselves return false; } - if (!$this->userManager->userExists($userId)) { - return false; - } - try { - $participant = $room->getParticipant($userId, false); - $notificationLevel = $participant->getAttendee()->getNotificationLevel(); + if (!$attendee instanceof Attendee) { + if (!$this->userManager->userExists($userId)) { + return false; + } + + $participant = $room->getParticipant($userId, false); + $attendee = $participant->getAttendee(); + } + + $notificationLevel = $attendee->getNotificationLevel(); if ($notificationLevel === Participant::NOTIFY_DEFAULT) { if ($room->getType() === Room::TYPE_ONE_TO_ONE) { $notificationLevel = Participant::NOTIFY_ALWAYS; From 4733de614c27948ad0676f9e23f4a25b1ca9ddc1 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 4 Mar 2022 12:32:58 +0100 Subject: [PATCH 13/13] Add chat case of company call Signed-off-by: Joas Schilling --- .../features/chat/company-call.feature | 220 ++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 tests/integration/features/chat/company-call.feature diff --git a/tests/integration/features/chat/company-call.feature b/tests/integration/features/chat/company-call.feature new file mode 100644 index 00000000000..1e4668364e1 --- /dev/null +++ b/tests/integration/features/chat/company-call.feature @@ -0,0 +1,220 @@ +Feature: callapi/company-call + Background: + Given group "company" exists + And user "employee1" exists + And user "employee1" is member of group "company" + And user "employee2" exists + And user "employee2" is member of group "company" + And user "employee3" exists + And user "employee3" is member of group "company" + And user "employee4" exists + And user "employee4" is member of group "company" + And user "employee5" exists + And user "employee5" is member of group "company" + And user "employee6" exists + And user "employee6" is member of group "company" + And user "employee7" exists + And user "employee7" is member of group "company" + And user "employee8" exists + And user "employee8" is member of group "company" + And user "employee9" exists + And user "employee9" is member of group "company" + And user "employee10" exists + And user "employee10" is member of group "company" + And user "employee11" exists + And user "employee11" is member of group "company" + And user "employee12" exists + And user "employee12" is member of group "company" + And user "employee13" exists + And user "employee13" is member of group "company" + And user "employee14" exists + And user "employee14" is member of group "company" + And user "employee15" exists + And user "employee15" is member of group "company" + And user "employee16" exists + And user "employee16" is member of group "company" + And user "employee17" exists + And user "employee17" is member of group "company" + And user "employee18" exists + And user "employee18" is member of group "company" + And user "employee19" exists + And user "employee19" is member of group "company" + And user "employee20" exists + And user "employee20" is member of group "company" + And user "employee21" exists + And user "employee21" is member of group "company" + And user "employee22" exists + And user "employee22" is member of group "company" + And user "employee23" exists + And user "employee23" is member of group "company" + And user "employee24" exists + And user "employee24" is member of group "company" + And user "employee25" exists + And user "employee25" is member of group "company" + And user "employee26" exists + And user "employee26" is member of group "company" + And user "employee27" exists + And user "employee27" is member of group "company" + And user "employee28" exists + And user "employee28" is member of group "company" + And user "employee29" exists + And user "employee29" is member of group "company" + And user "employee30" exists + And user "employee30" is member of group "company" + And user "employee31" exists + And user "employee31" is member of group "company" + And user "employee32" exists + And user "employee32" is member of group "company" + And user "employee33" exists + And user "employee33" is member of group "company" + And user "employee34" exists + And user "employee34" is member of group "company" + And user "employee35" exists + And user "employee35" is member of group "company" + And user "employee36" exists + And user "employee36" is member of group "company" + And user "employee37" exists + And user "employee37" is member of group "company" + And user "employee38" exists + And user "employee38" is member of group "company" + And user "employee39" exists + And user "employee39" is member of group "company" + And user "employee40" exists + And user "employee40" is member of group "company" + And user "employee41" exists + And user "employee41" is member of group "company" + And user "employee42" exists + And user "employee42" is member of group "company" + And user "employee43" exists + And user "employee43" is member of group "company" + And user "employee44" exists + And user "employee44" is member of group "company" + And user "employee45" exists + And user "employee45" is member of group "company" + And user "employee46" exists + And user "employee46" is member of group "company" + And user "employee47" exists + And user "employee47" is member of group "company" + And user "employee48" exists + And user "employee48" is member of group "company" + And user "employee49" exists + And user "employee49" is member of group "company" + And user "employee50" exists + And user "employee50" is member of group "company" + And user "employee51" exists + And user "employee51" is member of group "company" + And user "employee52" exists + And user "employee52" is member of group "company" + And user "employee53" exists + And user "employee53" is member of group "company" + And user "employee54" exists + And user "employee54" is member of group "company" + And user "employee55" exists + And user "employee55" is member of group "company" + And user "employee56" exists + And user "employee56" is member of group "company" + And user "employee57" exists + And user "employee57" is member of group "company" + And user "employee58" exists + And user "employee58" is member of group "company" + And user "employee59" exists + And user "employee59" is member of group "company" + And user "employee60" exists + And user "employee60" is member of group "company" + And user "employee61" exists + And user "employee61" is member of group "company" + And user "employee62" exists + And user "employee62" is member of group "company" + And user "employee63" exists + And user "employee63" is member of group "company" + And user "employee64" exists + And user "employee64" is member of group "company" + And user "employee65" exists + And user "employee65" is member of group "company" + And user "employee66" exists + And user "employee66" is member of group "company" + And user "employee67" exists + And user "employee67" is member of group "company" + And user "employee68" exists + And user "employee68" is member of group "company" + And user "employee69" exists + And user "employee69" is member of group "company" + And user "employee70" exists + And user "employee70" is member of group "company" + + Scenario: Company call + Then user "employee1" is participant of the following rooms (v4) + Then user "employee2" is participant of the following rooms (v4) + Then user "employee3" is participant of the following rooms (v4) + Then user "employee4" is participant of the following rooms (v4) + Then user "employee5" is participant of the following rooms (v4) + Then user "employee6" is participant of the following rooms (v4) + Then user "employee7" is participant of the following rooms (v4) + Then user "employee8" is participant of the following rooms (v4) + Then user "employee9" is participant of the following rooms (v4) + Then user "employee10" is participant of the following rooms (v4) + Then user "employee11" is participant of the following rooms (v4) + Then user "employee12" is participant of the following rooms (v4) + Then user "employee13" is participant of the following rooms (v4) + Then user "employee14" is participant of the following rooms (v4) + Then user "employee15" is participant of the following rooms (v4) + Then user "employee16" is participant of the following rooms (v4) + Then user "employee17" is participant of the following rooms (v4) + Then user "employee18" is participant of the following rooms (v4) + Then user "employee19" is participant of the following rooms (v4) + Then user "employee20" is participant of the following rooms (v4) + Then user "employee21" is participant of the following rooms (v4) + Then user "employee22" is participant of the following rooms (v4) + Then user "employee23" is participant of the following rooms (v4) + Then user "employee24" is participant of the following rooms (v4) + Then user "employee25" is participant of the following rooms (v4) + Then user "employee26" is participant of the following rooms (v4) + Then user "employee27" is participant of the following rooms (v4) + Then user "employee28" is participant of the following rooms (v4) + Then user "employee29" is participant of the following rooms (v4) + Then user "employee30" is participant of the following rooms (v4) + Then user "employee31" is participant of the following rooms (v4) + Then user "employee32" is participant of the following rooms (v4) + Then user "employee33" is participant of the following rooms (v4) + Then user "employee34" is participant of the following rooms (v4) + Then user "employee35" is participant of the following rooms (v4) + Then user "employee36" is participant of the following rooms (v4) + Then user "employee37" is participant of the following rooms (v4) + Then user "employee38" is participant of the following rooms (v4) + Then user "employee39" is participant of the following rooms (v4) + Then user "employee40" is participant of the following rooms (v4) + Then user "employee41" is participant of the following rooms (v4) + Then user "employee42" is participant of the following rooms (v4) + Then user "employee43" is participant of the following rooms (v4) + Then user "employee44" is participant of the following rooms (v4) + Then user "employee45" is participant of the following rooms (v4) + Then user "employee46" is participant of the following rooms (v4) + Then user "employee47" is participant of the following rooms (v4) + Then user "employee48" is participant of the following rooms (v4) + Then user "employee49" is participant of the following rooms (v4) + Then user "employee50" is participant of the following rooms (v4) + Then user "employee51" is participant of the following rooms (v4) + Then user "employee52" is participant of the following rooms (v4) + Then user "employee53" is participant of the following rooms (v4) + Then user "employee54" is participant of the following rooms (v4) + Then user "employee55" is participant of the following rooms (v4) + Then user "employee56" is participant of the following rooms (v4) + Then user "employee57" is participant of the following rooms (v4) + Then user "employee58" is participant of the following rooms (v4) + Then user "employee59" is participant of the following rooms (v4) + Then user "employee60" is participant of the following rooms (v4) + Then user "employee61" is participant of the following rooms (v4) + Then user "employee62" is participant of the following rooms (v4) + Then user "employee63" is participant of the following rooms (v4) + Then user "employee64" is participant of the following rooms (v4) + Then user "employee65" is participant of the following rooms (v4) + Then user "employee66" is participant of the following rooms (v4) + Then user "employee67" is participant of the following rooms (v4) + Then user "employee68" is participant of the following rooms (v4) + Then user "employee69" is participant of the following rooms (v4) + Then user "employee70" is participant of the following rooms (v4) + When user "employee1" creates room "room" (v4) + | roomType | 2 | + | invite | company | + When user "employee1" sends message "Message 1" to room "room" with 201 + When user "employee1" sends message "Message 2 @all" to room "room" with 201